ubuntu-make-16.11.1ubuntu1/0000775000000000000000000000000013135606406012336 5ustar ubuntu-make-16.11.1ubuntu1/COPYING0000664000000000000000000010451313013560574013375 0ustar 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 . ubuntu-make-16.11.1ubuntu1/Dockerfile0000664000000000000000000000657413013560574014344 0ustar # Docker container for Ubuntu Make # this installs a full ubuntu desktop environment in an # unprivileged container, and adds a passwordless sudo user. # This enables running medium tests of umake. FROM ubuntu:14.04 MAINTAINER Didier Roche # Set the env variable DEBIAN_FRONTEND to noninteractive ENV DEBIAN_FRONTEND noninteractive #Set default locale ENV LANG C.UTF-8 RUN locale-gen en_US.UTF-8 ADD debian/control /tmp/ ADD docker/umake_docker.pub /tmp/ ADD tests/data/developer.android.com.crt /usr/local/share/ca-certificates/ ADD tests/data/www.eclipse.org.crt /usr/local/share/ca-certificates/ ADD tests/data/data.services.jetbrains.com.crt /usr/local/share/ca-certificates/ ADD tests/data/golang.org.crt /usr/local/share/ca-certificates/ ADD tests/data/www.mozilla.org.crt /usr/local/share/ca-certificates/ ADD tests/data/code.visualstudio.com.crt /usr/local/share/ca-certificates/ ADD tests/data/api.dartlang.org.crt /usr/local/share/ca-certificates/ ADD tests/data/storage.googleapis.com.crt /usr/local/share/ca-certificates/ ADD tests/data/netbeans.org.crt /usr/local/share/ca-certificates/ ADD tests/data/www.rust-lang.org.crt /usr/local/share/ca-certificates/ ADD tests/data/static.rust-lang.org.crt /usr/local/share/ca-certificates/ ADD tests/data/swift.org.crt /usr/local/share/ca-certificates/ ADD tests/data/nodejs.org.crt /usr/local/share/ca-certificates/ ADD tests/data/github.com.crt /usr/local/share/ca-certificates/ ADD tests/data/api.github.com.crt /usr/local/share/ca-certificates/ ADD tests/data/spring.io.crt /usr/local/share/ca-certificates/ ADD tests/data/dl.google.com.crt /usr/local/share/ca-certificates/ ADD tests/data/sublimetext.com.crt /usr/local/share/ca-certificates/ ADD tests/data/download.sublimetext.com.crt /usr/local/share/ca-certificates/ ADD tests/data/community.unity.com.crt /usr/local/share/ca-certificates/ ADD docker/create_packages.sh /tmp/ # Refresh the image RUN \ apt-get update && \ apt-get dist-upgrade -y && \ # install add-apt-repository and tools to create build-deps apt-get install -y software-properties-common devscripts equivs dpkg-dev && \ # add umake ppa add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make && \ apt-get update && \ # install umake build-deps mk-build-deps /tmp/control -i --tool 'apt-get --yes' && \ # for running it as a daemon (and ssh requires the sshd directory) apt-get install openssh-server -y && \ mkdir /var/run/sshd && \ # disable DNS to not wait on host name resolution (delay when working offline) echo "UseDNS no" >> /etc/ssh/sshd_config && \ echo 'EXTRA_GROUPS="adm cdrom sudo dip plugdev fuse"' >> /etc/adduser.conf && \ echo 'ADD_EXTRA_GROUPS=1' >> /etc/adduser.conf && \ echo "user ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/bar && \ adduser --disabled-password --gecos "" user && \ echo user:user | chpasswd && \ # add the ubuntu make ssh key to the list of authorized ones mkdir -p /home/user/.ssh && \ cat /tmp/umake_docker.pub >> /home/user/.ssh/authorized_keys && \ chown -R user:user /home/user/ && \ # Twisted for a mock FTP server. apt-get install python-twisted-core -y && \ # add certificates update-ca-certificates && \ # finally remove all ppas and add local repository rm /etc/apt/sources.list.d/* && \ /tmp/create_packages.sh /apt-fake-repo && \ # clean up stuff apt-get clean -y && \ apt-get remove --purge -y software-properties-common devscripts equivs ubuntu-make-16.11.1ubuntu1/confs/0000775000000000000000000000000013013560574013446 5ustar ubuntu-make-16.11.1ubuntu1/confs/info.logcfg0000664000000000000000000000046413013560574015570 0ustar version: 1 disable_existing_loggers: True formatters: simple: format: "[%(name)s] %(levelname)s: %(message)s" handlers: console: class: logging.StreamHandler level: INFO formatter: simple stream: ext://sys.stdout root: level: INFO handlers: [console] ubuntu-make-16.11.1ubuntu1/confs/completions/0000775000000000000000000000000013013560574016002 5ustar ubuntu-make-16.11.1ubuntu1/confs/completions/_umake0000664000000000000000000000017413013560574017170 0ustar #compdef umake # we use bash global completion autoload -Uz bashcompinit bashcompinit source /etc/bash_completion.d/umake ubuntu-make-16.11.1ubuntu1/confs/debug.nose0000664000000000000000000000005013013560574015415 0ustar [nosetests] nocapture=1 nologcapture=1 ubuntu-make-16.11.1ubuntu1/confs/githooks/0000775000000000000000000000000013013560574015275 5ustar ubuntu-make-16.11.1ubuntu1/confs/githooks/pre-commit0000775000000000000000000000316513013560574017304 0ustar #!/bin/sh # # only have this pre-commit check on master if [ "`git name-rev --name-only HEAD`" != "master" ]; then exit 0 fi if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. ##We let download page being offending #git diff-index --check --cached $against -- # Run pep8 and small tests ##git stash -q --keep-index ./runtests pep8 small RESULT=$? ##git stash pop -q [ $RESULT -ne 0 ] && exit 1 exit 0 ubuntu-make-16.11.1ubuntu1/confs/githooks/prepare-commit-msg0000775000000000000000000000263713013560574020743 0ustar #!/bin/sh # # We ensure we bump everything needed when doing a release. # We do not use debcommit, but just put "releasing" in the changelog, # we match "releas", ignoring the case and change+tag version # 0. Ensuring that we have some UNRELEASED content in debian/changelog # 1. Compute the new release number, based on older umake/version # 2. We update umake/version with the new release number # 3. Bumping debian/changelog version as well # 4. Then, modifying the commit message itself to match the correct version grep -qi "create release" $1 found=$? set -e # we are releasing a version, generate the version if [ $found -eq 0 ]; then scriptdir=$(dirname $(readlink -f $0)) rootdir="$scriptdir/../.." releasingfile="$rootdir/.git/releasing" # if we are already releasing (and so, amending the commit), don't redo anything (avoid loop) if [ -f $releasingfile ]; then exit 0 fi head -1 ${rootdir}/debian/changelog | grep -q UNRELEASED if [ $? -ne 0 ]; then echo "This commits says that it's releasing, but no UNRELEASED in debian/changelog, exiting" exit 1 fi # get a new valid version. This updates umake/version as well version=$(${scriptdir}/update_version git add ${rootdir}/umake/version) dch -v ${version} "" dch -r "" --distribution zesty git add ${rootdir}/debian/changelog echo "releasing package ubuntu-make ${version}" > $1 fi ubuntu-make-16.11.1ubuntu1/confs/githooks/post-commit0000775000000000000000000000124013013560574017473 0ustar #!/bin/sh # # Amend and tag releasing commit to take into account added autogenerated # or updated files in the pre commit hooks. git log -1 HEAD | grep -qi "releasing package" found=$? set -e # we are on a release commit, add missing files and tag if [ $found -eq 0 ]; then rootdir="$(dirname $(readlink -f $0))/../.." releasingfile="$rootdir/.git/releasing" # if we are already releasing (and so, amending the commit), don't redo anything (avoid loop) if [ -f $releasingfile ]; then rm $releasingfile exit 0 fi touch $releasingfile git commit --amend -C HEAD --no-verify git tag -f $(cat ${rootdir}/umake/version) fi ubuntu-make-16.11.1ubuntu1/confs/githooks/update_version0000775000000000000000000000344713013560574020262 0ustar #!/usr/bin/python3 # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import datetime import os import sys if __name__ == '__main__': version_file_path = os.path.join(os.path.dirname(__file__), "..", "..", "umake", "version") version_tempfile_path = "{}.new".format(version_file_path) version = '{:%y.%m}'.format(datetime.datetime.now()) old_version = open(version_file_path, 'r', encoding='utf-8').read().strip() if old_version[0:5] == version: minor = old_version[6:] # need to bump to a minor version if minor: try: minor = int(minor) + 1 version += ".{}".format(minor) except ValueError: print("{} hasn't the expected format: YY.MM.".format(old_version)) sys.exit(1) # there was no minor version, so add first one else: version += ".1" # write new version file with open(version_tempfile_path, 'w', encoding="utf-8") as f: f.write(version) f.flush() os.fsync(f.fileno()) os.rename(version_tempfile_path, version_file_path) print(version) ubuntu-make-16.11.1ubuntu1/confs/coverage.cov0000664000000000000000000000011613013560574015750 0ustar # coverage should export html to coverage-html [html] directory=html-coverage ubuntu-make-16.11.1ubuntu1/confs/debug.logcfg0000664000000000000000000000121113013560574015712 0ustar version: 1 disable_existing_loggers: False formatters: simple: format: "[%(name)s] %(levelname)s: %(message)s" with_time: format: "%(asctime)s [%(name)s] %(levelname)s: %(message)s" handlers: console: class: logging.StreamHandler level: DEBUG formatter: simple stream: ext://sys.stdout debug_file_handler: class: logging.handlers.RotatingFileHandler level: DEBUG formatter: with_time filename: debug.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 root: level: DEBUG handlers: [console, debug_file_handler] ubuntu-make-16.11.1ubuntu1/confs/testingsubprocess.logcfg0000664000000000000000000000222213013560574020415 0ustar version: 1 disable_existing_loggers: False formatters: simple: format: "[%(name)s] %(levelname)s: %(message)s" with_time: format: "%(asctime)s [%(name)s] %(levelname)s: %(message)s" handlers: console: class: logging.StreamHandler level: WARNING formatter: simple stream: ext://sys.stdout debug_file_handler: class: logging.handlers.RotatingFileHandler level: DEBUG formatter: with_time filename: debug.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 info_file_handler: class: logging.handlers.RotatingFileHandler level: INFO formatter: with_time filename: info.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 warn_error_file_handler: class: logging.handlers.RotatingFileHandler level: WARNING formatter: with_time filename: errors.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 root: level: DEBUG handlers: [console, debug_file_handler, info_file_handler, warn_error_file_handler] ubuntu-make-16.11.1ubuntu1/confs/prod.nose0000664000000000000000000000014013013560574015273 0ustar [nosetests] with-cov=1 cov=umake cov-report=term-missing,html,xml cov-config=confs/coverage.cov ubuntu-make-16.11.1ubuntu1/confs/testing.logcfg0000664000000000000000000000200513013560574016303 0ustar version: 1 disable_existing_loggers: False formatters: simple: format: "[%(name)s] %(levelname)s: %(message)s" with_time: format: "%(asctime)s [%(name)s] %(levelname)s: %(message)s" handlers: debug_file_handler: class: logging.handlers.RotatingFileHandler level: DEBUG formatter: with_time filename: debug.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 info_file_handler: class: logging.handlers.RotatingFileHandler level: INFO formatter: with_time filename: info.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 warn_error_file_handler: class: logging.handlers.RotatingFileHandler level: WARNING formatter: with_time filename: errors.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 root: level: DEBUG handlers: [debug_file_handler, info_file_handler, warn_error_file_handler] ubuntu-make-16.11.1ubuntu1/confs/debug_network.logcfg0000664000000000000000000000140213013560574017465 0ustar version: 1 disable_existing_loggers: False formatters: simple: format: "[%(name)s] %(levelname)s: %(message)s" with_time: format: "%(asctime)s [%(name)s] %(levelname)s: %(message)s" handlers: console: class: logging.StreamHandler level: DEBUG formatter: simple stream: ext://sys.stdout debug_network_file_handler: class: logging.handlers.RotatingFileHandler level: DEBUG formatter: with_time filename: debug_network.log maxBytes: 10485760 # 10MB backupCount: 20 encoding: utf8 loggers: umake.network: level: DEBUG handlers: [console, debug_network_file_handler] propagate: no root: level: INFO handlers: [console] ubuntu-make-16.11.1ubuntu1/.pep80000664000000000000000000000017613013560574013217 0ustar [pep8] exclude = env/ max-line-length = 120 # ignore "Identation is not multiple of 4" for continuation line ignore = "E111" ubuntu-make-16.11.1ubuntu1/runtests0000775000000000000000000003775613013560574014175 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import argparse import configparser import logging import logging.config import nose import os import yaml import shutil import subprocess import sys import tempfile root_dir = os.path.abspath(os.path.dirname(__file__)) config_dir = os.path.join(root_dir, 'confs') DEBUG_CONFIG_FILE = os.path.join(config_dir, "debug.nose") COVERAGE_CONFIG_FILE = os.path.join(config_dir, "prod.nose") TESTS_DIR = os.path.join(root_dir, 'tests') DEBUG_LOG_CONFIG = os.path.join(config_dir, "debug.logcfg") TESTING_LOG_CONFIG = os.path.join(config_dir, "testing.logcfg") # subprocess need to output on stdout the logs to be monitored # the profile is the testing one + console output in warning mode TESTING_SUBPROCESS_LOG_CONFIG = os.path.join(config_dir, "testing.subprocess.logcfg") def transform_nose_config_to_cmd(filename): """Manually transform a nose config file to a cmd parameters This is needed in case the same parameter is repeated multiple times This return the cmd line array parameters.""" cmd_line = [] config = configparser.ConfigParser() config.read(filename) for key in config["nosetests"]: value = config["nosetests"][key] if value == '1': cmd_line.append('--' + key) # multiple values (what the config parameter for nose doesn't support) elif ',' in value: for val in value.split(','): cmd_line.append('--{}={}'.format(key, val)) else: cmd_line.append('--{}={}'.format(key, value)) return cmd_line def set_logging_profile(log_config_file): """Set logging profile for current process and subprocesses""" with open(log_config_file, 'rt') as f: logging_config = yaml.load(f.read()) logging.config.dictConfig(logging_config) os.environ["LOG_CFG"] = log_config_file if log_config_file == TESTING_LOG_CONFIG: os.environ["LOG_CFG"] = TESTING_SUBPROCESS_LOG_CONFIG def local_run(args): """Run directly the tests on the host""" # setup the environment in plain english so that we standardize the test bed (if some people have some .mo # Ubuntu Make files installed while having a locale set to it) to avoid getting translated strings not # matching our expectations. os.environ["LANGUAGE"] = "C" nose_args = [] # nosetests captured logs format nose_args.extend(["--logging-format", "%(asctime)s [%(name)s] %(levelname)s: %(message)s"]) ## handle config first specified_config = False if args.config: nose_args.extend(["--config", args.config]) specified_config = True elif args.debug: nose_args.extend(["--config", DEBUG_CONFIG_FILE]) set_logging_profile(DEBUG_LOG_CONFIG) specified_config = True elif args.coverage: nose_args.extend(transform_nose_config_to_cmd(COVERAGE_CONFIG_FILE)) set_logging_profile(TESTING_LOG_CONFIG) specified_config = True elif args.no_config: specified_config = True ## output xunit and json if requested if args.publish: nose_args.append("--with-xunit") # FIXME: disable nose-json for now, incompatible with coverage reporting when an exception is raised. # we are going to switch to nose2 anyway. #nose_args.append("--with-json") ## check if we want to run those tests with the system code if args.system: nose_args.append("-P") # let remove it from there as well sys.path.remove(root_dir) else: import tests tests.tools.set_local_umake() if not "all" in args.tests and len(args.tests) > 0: for test_type in args.tests: for named_test_type in ("small", "medium", "large", "pep8"): if test_type == named_test_type: if test_type == "pep8": nose_args.append(os.path.join(TESTS_DIR, "__init__.py")) else: nose_args.append(os.path.join(TESTS_DIR, named_test_type)) break # Not a named test_type, but a list of tests to run else: nose_args.append(test_type) # If no config is given, choose debug by default for partial run if not specified_config: nose_args.extend(["--config", DEBUG_CONFIG_FILE]) set_logging_profile(DEBUG_LOG_CONFIG) specified_config = True else: # If no config is given, run with coverage if not specified_config: nose_args.extend(transform_nose_config_to_cmd(COVERAGE_CONFIG_FILE)) set_logging_profile(TESTING_LOG_CONFIG) specified_config = True ## need a fake $0 argument nose_args.insert(0, "") nose.main(argv=nose_args) def vm_run(args): """Run the tests on a qemu vm""" artefacts_dir = tempfile.mkdtemp(prefix="umake-test-artefacts-") cmds = ['adt-run', '-s', # add ubuntu-make and ubuntu-make-builddeps ppas with their gpg key '--setup-commands', """apt-key adv --keyserver keyserver.ubuntu.com --recv-key 399B698EEA9EF163B6F9A0F62CC98497A1231595; echo "deb http://ppa.launchpad.net/ubuntu-desktop/ubuntu-make-builddeps/ubuntu trusty main" > /etc/apt/sources.list.d/autopkgtest-ubuntu-desktop-ubuntu-make-builddeps.list; echo "deb-src http://ppa.launchpad.net/ubuntu-desktop/ubuntu-make-builddeps/ubuntu trusty main" >> /etc/apt/sources.list.d/autopkgtest-ubuntu-desktop-ubuntu-make-builddeps.list; echo "deb http://ppa.launchpad.net/ubuntu-desktop/ubuntu-make/ubuntu trusty main" > /etc/apt/sources.list.d/autopkgtest-ubuntu-desktop-ubuntu-make.list; echo "deb-src http://ppa.launchpad.net/ubuntu-desktop/ubuntu-make/ubuntu trusty main" >> /etc/apt/sources.list.d/autopkgtest-ubuntu-desktop-ubuntu-make.list; apt-get update""", # artefacts saving "--output-dir", artefacts_dir, # env variables setting up tests '--env', "TESTS={}".format(' '.join(args.tests))] # default target to test is current tree target = ['--built-tree', '.'] # test package from archive or ppa (the most recent) if args.test_package: target = ["--apt-source", "ubuntu-make"] # git checkout testing if args.test_git: target = ['--no-built-binaries', "--git-source", args.test_git] # local source package testing if args.test_source: target = ["--source", args.test_source] cmds.extend(target) # add emulator options cmds.extend(['---', 'qemu', '-o', '/var/tmp', args.image]) try: return_code = subprocess.call(cmds) print("Artefacts are available at {}".format(artefacts_dir)) except FileNotFoundError: print("adt-run isn't installed.") shutil.rmtree(artefacts_dir) return_code = 1 sys.exit(return_code) def remote_run(args): """Start a run on the official ubuntu instances""" # Note that we wrap arguments containing spaces with double quoting as they are passed through ssh # ssh connection to snakefruit cmds = ["ssh", "snakefruit.canonical.com", "sudo", "-i", "-u", "ubuntu-archive", # run-autopkgtest command "run-autopkgtest", "-s", args.series, # ensure we always add the ppa to be in correct swift container archive "--ppa", "ubuntu-desktop/ubuntu-make-builddeps", "--ppa", "ubuntu-desktop/ubuntu-make", # env variables setting up tests (with double quoting '--env', "'TESTS={}'".format(' '.join(args.tests))] # add architectures if any: for arch in args.architecture: cmds.extend(["-a", arch]) target = [] if args.test_package: target = ["ubuntu-make"] # git checkout testing, put results under ubuntu-make-git tag if args.test_git: target = ["--test-git", "'{}'".format(args.test_git), "ubuntu-make-git"] cmds.extend(target) sys.exit(subprocess.call(cmds)) def add_tests_arg(parser): """add the generic tests arguments to the parser""" parser.add_argument("tests", nargs='*', help="Action to perform: all (or omitted) to run all tests. " "small/medium/large/pep8 or nose syntax: " "tests.small.test_frameworks_loader:TestFrameworkLoaderSaveConfig.foo") class _GlobalHelp(argparse._HelpAction): def __call__(self, parser, namespace, values, option_string=None): parser.print_help() # retrieve local subparser from parser subparsers_actions = [ action for action in parser._actions if isinstance(action, argparse._SubParsersAction)] print(""" ------------------------------------------- Default mode is 'local' and can be omitted. -------------------------------------------""") subparsers_actions[0].choices['local'].print_help() parser.exit() if __name__ == '__main__': # ensure we have the right chmod on the ssh key to connect to docker containers (git by default reverts to x44) os.chmod(os.path.join(root_dir, "docker", "umake_docker"), 0o600) parser = argparse.ArgumentParser(description="Run umake tests. Specified list of test run in debug mode. " "Running a partial suite of tests is using a normal mode. " "Running all tests is using coverage by default.", add_help=False) parser.add_argument('--help', action=_GlobalHelp, help='Show this help') command_group = parser.add_subparsers(help='What mode to run tests with') local_mode = command_group.add_parser('local', help='run tests locally (default). Enable easy debugging but large ' 'tests requires sudo and impact your sessions.') vm_mode = command_group.add_parser('vm', help='run tests with vm_mode running on a qemu image.') remote_mode = command_group.add_parser('remote', help='run on official autopkgtests ubuntu instances (only for ' 'ubuntu archive admins or release team members)') ## local options local_mode.set_defaults(run=local_run) add_tests_arg(local_mode) local_mode.add_argument('-s', "--system", action="store_true", help="Use system umake instead of local one") local_mode.add_argument("--publish", action="store_true", help="Publish xunit results format") config_group = local_mode.add_argument_group('Run configuration options', description="The default configuration is to use the debug profile " "when running some manually specific list of tests. No profile is " "selected when running some suites of tests and coverage " "profile when selecting all tests.")\ .add_mutually_exclusive_group() config_group.add_argument("-c", "--config", help="Force using a particular nose profile, disable autoselection") config_group.add_argument("--coverage", action="store_true", help="Force using coverage profile even when some " "tests or tessuite") config_group.add_argument("--debug", action="store_true", help="Force using debug profile even when running " "all tests") config_group.add_argument("--no-config", action="store_true", help="Disable any automated or manual config " "selection") ## vm options vm_mode.set_defaults(run=vm_run) vm_mode.add_argument('image', metavar="image_path", help="Image against which running the tests. This is what " "determines as well the release and arch against which " "we are testing on. You can build one cloud image via: " "'buildvm-ubuntu-cloud -r trusty' for instance.") add_tests_arg(vm_mode) target_group = vm_mode.add_argument_group('Ubuntu Make test target', description="This defines which Ubuntu Make you want to test. Default " "is the local tree (what's your pwd). You can change it " "for a git tree/branch or package from archive.")\ .add_mutually_exclusive_group() target_group.add_argument("--test-git", metavar='GITURL [branchname]', help="A single URL or URL branchname. The test will be git cloned from " "that URL and ran from the checkout. This will not build binary " "packages from the branch and run tests against those, the test " "dependencies will be taken from the archive, or Ubuntu Make PPA.") target_group.add_argument("--test-package", action="store_true", help="Test the ubuntu-make package (system run) " "from the archive or Ubuntu Make PPA.") target_group.add_argument("--test-source", metavar='DSC or some/pkg.dsc', help='Build DSC and use its tests and/or generated binary packages') ## remote options remote_mode.set_defaults(run=remote_run) remote_mode.add_argument("series", help='Distro series name.') add_tests_arg(remote_mode) remote_mode.add_argument('-a', '--architecture', action='append', default=[], help='Only run test(s) on given architecture name(s). ' 'Can be specified multiple times (default: all).') target_group = remote_mode.add_argument_group('Ubuntu Make test target', description="This defines which Ubuntu Make you want to test. You " "can change between a git tree/branch of package from " "archive.")\ .add_mutually_exclusive_group(required=True) target_group.add_argument("--test-package", action="store_true", help="Test the ubuntu-make package (system run) " "from the archive or Ubuntu Make PPA.") target_group.add_argument("--test-git", metavar='GITURL [branchname]', help="A single URL or URL branchname. The test will be git cloned from " "that URL and ran from the checkout. This will not build binary " "packages from the branch and run tests against those, the test " "dependencies will be taken from the archive, or Ubuntu Make PPA.") # set local as default and parse cmd = sys.argv[1:] if "--help" not in cmd: if cmd[0] not in ["local", "vm", "remote"]: cmd.insert(0, "local") args = parser.parse_args(cmd) args.run(args) ubuntu-make-16.11.1ubuntu1/docker/0000775000000000000000000000000013013560574013605 5ustar ubuntu-make-16.11.1ubuntu1/docker/create_packages.sh0000775000000000000000000001041513013560574017246 0ustar #!/bin/bash repo_root_dir=$1 generate_package (){ temp_dir="/tmp/package" package_name=$1 version=$2 arch=$3 multiarch=true if [ -z "$arch" ]; then arch=$(dpkg --print-architecture) multiarch=false fi mkdir -p $temp_dir/DEBIAN control_file=$temp_dir/DEBIAN/control echo "Package: $package_name Source: testpackage Version: $version Architecture: $arch Maintainer: Didier Roche Installed-Size: 26 Section: misc Priority: extra" > $control_file [[ $multiarch == true ]] && echo "Multi-Arch: same" >> $control_file echo "Description: Dummy package for testing Package used for testing debs installation" >> $control_file dpkg-deb -b $temp_dir ${package_name}_${version,}_${arch}.deb rm -rf $temp_dir } extract_version() { version=$(apt-cache policy $1 | grep Candidate | awk '{print $2}') [ -z "$version" ] && version=1.0 echo $version } create_package() { package_name=$1 arch=$2 version=$(extract_version $package_name) generate_package $package_name $version $arch } # android studio and adt deps mkdir -p $repo_root_dir/android cd $repo_root_dir/android create_package clang create_package openjdk-7-jdk create_package openjdk-8-jdk create_package jayatana create_package libncurses5 i386 create_package libstdc++6 i386 create_package zlib1g i386 dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # rubymine deps mkdir -p $repo_root_dir/rubymine cd $repo_root_dir/rubymine create_package ruby dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # stencyl deps mkdir -p $repo_root_dir/stencyl cd $repo_root_dir/stencyl create_package libxtst6 i386 create_package libxext6 i386 create_package libxi6 i386 create_package libncurses5 i386 create_package libxt6 i386 create_package libxpm4 i386 create_package libxmu6 i386 create_package libxp6 i386 create_package libgtk2.0-0 i386 create_package libatk1.0-0 i386 create_package libc6 i386 create_package libcairo2 i386 create_package libexpat1 i386 create_package libfontconfig1 i386 create_package libfreetype6 i386 create_package libglib2.0-0 i386 create_package libice6 i386 create_package libpango1.0-0 i386 create_package libpng12-0 i386 create_package libsm6 i386 create_package libxau6 i386 create_package libxcursor1 i386 create_package libxdmcp6 i386 create_package libxfixes3 i386 create_package libx11-6 i386 create_package libxinerama1 i386 create_package libxrandr2 i386 create_package libxrender1 i386 create_package zlib1g i386 create_package libnss3-1d i386 create_package libnspr4-0d i386 create_package libcurl3 i386 create_package libasound2 i386 dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # visual studio code deps mkdir -p $repo_root_dir/vscode cd $repo_root_dir/vscode create_package libgtk2.0-0 dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # arduino deps mkdir -p $repo_root_dir/arduino cd $repo_root_dir/arduino create_package gcc-avr create_package avr-libc dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # scala deps mkdir -p $repo_root_dir/scala cd $repo_root_dir/scala create_package openjdk-7-jre create_package openjdk-8-jre dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # kotlin deps mkdir -p $repo_root_dir/kotlin cd $repo_root_dir/kotlin create_package openjdk-7-jre create_package openjdk-8-jre dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # swift deps mkdir -p $repo_root_dir/swift cd $repo_root_dir/swift create_package clang create_package libicu-dev dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz # unity3d deps mkdir -p $repo_root_dir/unity3d cd $repo_root_dir/unity3d create_package gconf-service create_package lib32gcc1 create_package lib32stdc++6 create_package libasound2 create_package libcairo2 create_package libcap2 create_package libcups2 create_package libfontconfig1 create_package libfreetype6 create_package libgconf-2-4 create_package libgdk-pixbuf2.0-0 create_package libgl1-mesa-glx create_package libglu1-mesa create_package libgtk2.0-0 create_package libnspr4 create_package libnss3 create_package libpango1.0-0 create_package libpq5 create_package libxcomposite1 create_package libxcursor1 create_package libxdamage1 create_package libxext6 create_package libxfixes3 create_package libxi6 create_package libxrandr2 create_package libxrender1 create_package libxtst6 create_package monodevelop dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz ubuntu-make-16.11.1ubuntu1/docker/umake_docker.pub0000664000000000000000000000061413013560574016747 0ustar ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9iWeT1+JcYVzLUwqXJ4SnbpMmD2HhHBHAduFTLTFMHc5MZnwkHGzKiE3N9Usz7NRecnYzbmp5blx6bl0EabFmH8UrVwwiRJRhVyj67Xuyj07B0azOeIGpY561o8fsJX5D61IwFFqKao+J+ct3Nj2KJHHOKR9oJIkoPuEmdT81sBaKn9li137cUGbvPrppoNcWIIzEZ1q67SeeTsJrtOYharyGil2jwhjrXLUWm39ULZVHZSl0p06PcmgYLOTzxmOzPeVXmqxQhS7BimH8BOOACJuPeEGp0FYn41QOLiFIrcFtBOUbeYdU4x1arX0pWjaPj7LXC3tRQqdBcqJk38kX didrocks@tidus ubuntu-make-16.11.1ubuntu1/docker/umake_docker0000664000000000000000000000321313013560574016160 0ustar -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAvYlnk9fiXGFcy1MKlyeEp26TJg9h4RwRwHbhUy0xTB3OTGZ8 JBxsyohNzfVLM+zUXnJ2M25qeW5cem5dBGmxZh/FK1cMIkSUYVco+u17so9OwdGs zniBqWOetaPH7CV+Q+tSMBRaimqPifnLdzY9iiRxzikfaCSJKD7hJnU/NbAWip/Z Ytd+3FBm7z66aaDXFiCMxGdauu0nnk7Ca7TmIWq8hopdo8IY61y1Fpt/VC2VR2Up dKdOj3JoGCzk88Zjsz3lV5qsUIUuwYph/ATjgAibj3hBqdBWJ+NUDi4hSK3BbQTl G3mHVOMdWq19KVo2j4+y1wt7UUKnQXKiZN/JFwIDAQABAoIBABmN4Q0p2jciWWSA ebkPdu8sFWLYSBYVtr8ASDjyqubcTeg3GR21R2W3IuZV4CHMGIXzYMRmaqycmJNZ NelWZriiJ+9D+TrVjDvjiH7sbfURJUk0f9wGm1S/PbK3tki8dV2q6JXa6Koo29l6 eFhGU93ANCfbm4RrCKMId0q8HB2cuH2zJBiTv/GAjmXBOhIlNDEbydkt9kMGqmVV THh1pu9jGH+AnDfd0CBrW1IfRvjl49zkaEYq+FcWy/ksPFFMPKmiunPZWk+4jJUc aJ5goYtTmNGu4W/yEfFDGLPrGAkLNAhSs2s2ssnwSQynDs+9SGQFav5S7fI71oJG y67YL0ECgYEA8w7EeGCtn5UyqZmvAF0KD901INStHEfpzU5pD+y5xBh23kPDZw1a +Zn0AKwkcc4oI0w0EcjaUshJSQc82cncdSGQGTzlnE6t6Z/CEJd9HjZG5DmlHx17 AV5Z0PRXMqgalSQEfu1Pm22KFKqa6gXA970gn7CODp0kgO9S7K4UEu8CgYEAx6ER coQUiI5frwNKbgs4JQafxqZf+2+9xyHl4HQGn6EOhrBgaLmTC2+rz/RqCp8HRwV/ hBGwhJV4Eb1gEMxCTIBQJ+4YbuO+HPxv9cJdW3twtIROHoarRDwBhEnS4JnCbLvE 1uKoh99g0+5NWKZRvN8+xwS12uF+qgakWLkeDFkCgYB9ewA/TVoVawcuu+K3A1Fw gzksa9+7G/0+Ot7Ok94LuL2VXdKBX0m6Vpq7xiNChbX/ExZGoDTmS/RZuVzW6vnf lqY4AVJg8dWjKREdU7gKYucSaBgxCh04xacE00A5LMQcfu27QXS5v0FsDe/QJYxL 2d3/0zxjmwj/b46WFgDTDQKBgQCsD/kA0jT8inKQX268sLDgwPff+bELAAH77Ay9 zGOVHPVvRACk4yaJmePl5s2rf+x+249QHwsdC9OkvqxZbiTK2WG9OOwYT/Wh+Dbs BW4AFsJK5SqMBxkBRBMumY7IBd9dZu4/JLeL/Q3xPRmvihMzjtwGH9o64VcSZ40p 58ytaQKBgBd+1TYt0U2nk2P6nqQDtGi2IfaY0dllbhYzjrwIXyfcslFriXjdHRBh 1d0X7CoRLFIlGBbQL59JyHxBK06Fdeght37xXlfzv2QjMdexqL92jbEu2OpwKcZ3 1uso5EgxFZAamQ9DP+v4k8KL1hFUsYLi/xFlBIvzzmzIq40mvpnW -----END RSA PRIVATE KEY----- ubuntu-make-16.11.1ubuntu1/README.md0000664000000000000000000001614613013560574013625 0ustar # Ubuntu Make Ubuntu Make is a project designed to enable quick and easy setup of common needs for developers on Ubuntu. ## Current project health [![Build Status](https://api.travis-ci.org/ubuntu/ubuntu-make.svg?branch=master)](https://travis-ci.org/ubuntu/ubuntu-make) (pep8 and small tests) [All test results](https://jenkins.qa.ubuntu.com/job/udtc-trusty-tests/) and [Coverage report](https://jenkins.qa.ubuntu.com/job/udtc-trusty-tests-collect/label=ps-trusty-desktop-amd64-1/lastSuccessfulBuild/artifact/html-coverage/index.html) ## Installing We recommend to use the Ubuntu Make ppa to ensure you always have the latest and greatest version, even on older supported releases. We are available on the currently supported Ubuntu version. ```sh $ sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make $ sudo apt update $ sudo apt install ubuntu-make ``` ## Running the command line tool To run the tool: ```sh $ ./umake ``` You can use `--help` to get more information and change the verbosity of the output with `-v`, `-vv`. ## Requirements > Note that this project uses python3 and requires at least python 3.3. All commands use the python 3 version. There are directions later on explaining how to install the corresponding virtualenv. ## Shell completion To enable shell completion on bash or zsh, just run: ```sh $ . enable_completion ``` ## Different level of logging Multiple logging profiles are available in *confs/* to be able to have different traces of your execution (particularly useful for debugging). For instance, you will find: * **debug.logcfg**: Similar to using -vv, but also puts logs in a *debug.log*. * **debug_network.logcfg**: The root logging level is INFO (-v), the network activities are in DEBUG mode and will be logged in *debug_network.log*. * **testing.logcfg**: Mostly for coverage tests, do not set any logging config on stdout, but: * DEBUG logs and above are available in *debug.log*. * INFO logs and above are available in *info.log*. * WARNING and ERROR logs are available in *error.log*. Under normal circumstances, we expect *error.log* to remain empty../ To load one of those logging profiles: ```sh $ LOG_CFG=confs/debug.logcfg bin/umake ``` ## Development ### Providing user's framework It's possible for anyone to have local frameworks for either development purposes or for special local or team use-cases. * Any files in a directory set with the "UMAKE_FRAMEWORKS" environment variable will be loaded first. * Any files inside ~/.umake/frameworks will be loaded next. Any file should eventually contain a category or frameworks like the ones in umake/frameworks/*. If category names are duplicated only one will be loaded. Ubuntu Make will first load the one controlled by the environment variable, then the one located in the home based directory, and finally, the system one. Note that duplicate filenames are supported but not encouraged. ### Style guide and checking We are running pep8, but the max line length has been relaxed to 120. env/ is excluded from the pep8 check as well. Running this test, in particular: ```sh $ ./runtests pep8 ``` This will run those pep8 checks on the code. You can also run the pep8 tool directly from the project directory: ```sh $ pep8 . ``` ### Tests #### Types of tests There are four types of tests that can be combined in runtests: * **pep8**: Run the pep8 tests on all the umake and test code. * **small**: Tests modules and components with mock content around them. Note that this uses a local webserver (http and https) to serve mock content. * **medium**: Tests the whole workflow. It directly calls end user tools from the command line, but without affecting the local system. Requirements like installing packages are mocked, as well as the usage of a local webserver serving (smaller) content similar to what will be fetched in a real use case. The assets have the same formats and layout. * **large**: Runs the same tests as the medium test, but with real server downloads and installation of dpkg packages. Most of these tests need root privileges. Be aware that these tests only run on a graphical environment. It will interfere with it and it is likely to install or remove packages on your system. To run all the tests, with coverage report, like in our jenkins infra: ```sh $ ./runtests ``` Use `--no-config` to disable the coverage report selection. #### Running some tests with all debug infos By default, **runtests** will not display any debug output if the tests are successful, similar to Nose. However, if only some tests are selected, runtests will a display full debug log, ```sh $ ./runtests tests/small/test_tools.py:TestConfigHandler ``` Use `--no-config` to disable the debug output selection. #### More information on runtests **runtests** is a small nose wrapper used to simplify the testing process. By default, if no arguments are supplied or if "all" is supplied, runtests will run all available tests on the project using the production nose configuration. It is possible to run only some types of tests: ```sh $ ./runtests small medium ``` This will only run small and medium tests, with all nose defaults (no profile is selected). Finally, you can run a selection of one or more tests: ```sh $ ./runtests tests/small/test_tools.py:TestConfigHandler ``` This enables the debug profile by default, to display all outputs and logging information (in debug level). You can activate/disable/change any of those default selected configurations with **--config/--coverage/--debug/--no-config** (see `runtests --help` for more information) #### Nose configurations Some nose configurations are available in **confs/**. You will find: * **debug.nose**: this profile shows all outputs and logging information while turning debug logging on. * **prod.nose**: this profile keep all outputs captured, but display tests coverage results. #### Check for python warnings: **runtests** is compatible with showing the python warnings: ```sh $ PYTHONWARNINGS=d ./runtests ``` ### Create your own environment and run from it For an easier development workflow, we encourage the use of virtualenv to test and iterate on the project rather than installing all the requirements on your machine. In the project root directory run (env/ is already in .gitignore and excluded from pep8 checking): ```sh $ virtualenv --python=python3 --system-site-packages env $ sudo apt-get install -qq apt apt-utils libapt-pkg-dev # those are the requirements to compile python-apt $ sudo apt-get install -qq python3-gi # not installable with pypi $ sudo apt-get install -qq bzr python3-dev # requires for pip install -r $ env/bin/pip install -r requirements.txt $ source env/bin/activate $ bin/umake ``` ### Developing using system package Instead of using a virtual environment, you can install system packages to be able to run the Ubuntu Make tests. The build dependencies are listed in *debian/control* and should be available in latest development ubuntu version. If you are using the latest LTS, you should find them in a dedicated [Ubuntu Make Build-dep ppa](https://launchpad.net/~ubuntu-desktop/+archive/ubuntu/ubuntu-make-builddeps). ## Release management Refresh .pot files: ```sh $ ./setup.py update_pot ``` ubuntu-make-16.11.1ubuntu1/umake/0000775000000000000000000000000013135606406013440 5ustar ubuntu-make-16.11.1ubuntu1/umake/__init__.py0000664000000000000000000001123413013560574015552 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import argparse import gettext from gettext import gettext as _ import locale import logging import logging.config import os import sys from umake.frameworks import BaseCategory, load_frameworks from umake.tools import MainLoop from .ui import cli import yaml logger = logging.getLogger(__name__) # if set locale isn't installed, don't load up translations (we don't know what's the locale # user encoding is and python3 will fallback to ANSI_X3.4-1968, which isn't UTF-8 and creates # thus UnicodeEncodeError) try: locale.setlocale(locale.LC_ALL, '') gettext.textdomain("ubuntu-make") except locale.Error: logger.debug("Couldn't load default locale {}, fallback to English".format(locale.LC_ALL)) _default_log_level = logging.WARNING _datadir = None def _setup_logging(env_key='LOG_CFG', level=_default_log_level): """Setup logging configuration Order of preference: - manually define level - env_key env variable if set (logging config file) - fallback to _default_log_level """ path = os.getenv(env_key, '') logging.basicConfig(level=level, format="%(levelname)s: %(message)s") if level == _default_log_level: if os.path.exists(path): with open(path, 'rt') as f: config = yaml.load(f.read()) logging.config.dictConfig(config) logging.info("Logging level set to {}".format(logging.getLevelName(logging.root.getEffectiveLevel()))) def set_logging_from_args(args, parser): """Choose logging ignoring any unknown sys.argv options""" result_verbosity_arg = [] for arg in args: if arg.startswith("-v"): for char in arg: if char not in ['-', 'v']: break else: result_verbosity_arg.append(arg) args = parser.parse_args(result_verbosity_arg) # setup logging level if set by the command line if args.verbose == 1: _setup_logging(level=logging.INFO) elif args.verbose > 1: _setup_logging(level=logging.DEBUG) else: _setup_logging() class _HelpAction(argparse._HelpAction): def __call__(self, parser, namespace, values, option_string=None): parser.print_help() # retrieve subparsers from parser subparsers_actions = [ action for action in parser._actions if isinstance(action, argparse._SubParsersAction)] for subparsers_action in subparsers_actions: # get all subparsers and print help for choice, subparser in subparsers_action.choices.items(): print(_("* Command '{}':").format(choice)) print(subparser.format_help()) parser.exit() def main(): """Main entry point of the program""" if "udtc" in sys.argv[0]: print(_("WARNING: 'udtc' command is the previous name of Ubuntu Make. Please use the 'umake' command from now " "on providing the exact same features. The 'udtc' command will be removed soon.")) parser = argparse.ArgumentParser(description=_("Deploy and setup developers environment easily on ubuntu"), epilog=_("Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile."), add_help=False) parser.add_argument('--help', action=_HelpAction, help=_('Show this help')) # add custom help parser.add_argument("-v", "--verbose", action="count", default=0, help=_("Increase output verbosity (2 levels)")) parser.add_argument('-r', '--remove', action="store_true", help=_("Remove specified framework if installed")) parser.add_argument('--version', action="store_true", help=_("Print version and exit")) # set logging ignoring unknown options set_logging_from_args(sys.argv, parser) mainloop = MainLoop() # load frameworks and initialize parser load_frameworks() cli.main(parser) mainloop.run() ubuntu-make-16.11.1ubuntu1/umake/frameworks/0000775000000000000000000000000013135606406015620 5ustar ubuntu-make-16.11.1ubuntu1/umake/frameworks/dart.py0000664000000000000000000000720613013560574017131 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Dartlang module""" from contextlib import suppress from gettext import gettext as _ import logging import os import platform import re import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.network.download_center import DownloadItem from umake.tools import add_env_to_user, MainLoop from umake.ui import UI logger = logging.getLogger(__name__) _supported_archs = ['i386', 'amd64'] class DartCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Dart", description=_("Dartlang Development Environment"), logo_path=None) class DartLangEditorRemoval(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Dart Editor", description=_("Dart SDK with editor (not supported upstream anyymore)"), download_page=None, category=category, only_on_archs=_supported_archs, only_for_removal=True) class DartLang(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Dart SDK", description=_("Dart SDK (default)"), is_category_default=True, category=category, only_on_archs=_supported_archs, download_page="https://api.dartlang.org", dir_to_decompress_in_tarball="dart-sdk", required_files_path=[os.path.join("bin", "dart")]) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): """Get latest version and append files to download""" logger.debug("Set download metadata") error_msg = result[self.download_page].error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) version = '' version_re = r'Dart SDK ([\d\.]+)' for line in result[self.download_page].buffer: p = re.search(version_re, line.decode()) with suppress(AttributeError): version = p.group(1) break else: logger.error("Download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) tag_machine = 'x64' if platform.machine() == 'i686': tag_machine = 'ia32' url = "https://storage.googleapis.com/dart-archive/channels/stable/release/{}/sdk/dartsdk-linux-{}-release.zip"\ .format(version, tag_machine) logger.debug("Found download link for {}".format(url)) self.download_requests.append(DownloadItem(url, None)) self.start_download_and_install() def post_install(self): """Add go necessary env variables""" add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "bin")}}) UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name))) ubuntu-make-16.11.1ubuntu1/umake/frameworks/__init__.py0000664000000000000000000003767213013560574017750 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Base Handling functions and base class of backends""" import abc from contextlib import suppress from gettext import gettext as _ from importlib import import_module, reload import inspect import logging import os import pkgutil import sys import subprocess from umake.network.requirements_handler import RequirementsHandler from umake.settings import DEFAULT_INSTALL_TOOLS_PATH, UMAKE_FRAMEWORKS_ENVIRON_VARIABLE, DEFAULT_BINARY_LINK_PATH from umake.tools import ConfigHandler, NoneDict, classproperty, get_current_arch, get_current_ubuntu_version,\ is_completion_mode, switch_to_current_user, MainLoop, get_user_frameworks_path from umake.ui import UI logger = logging.getLogger(__name__) class BaseCategory(): """Base Category class to be inherited""" NOT_INSTALLED, PARTIALLY_INSTALLED, FULLY_INSTALLED = range(3) categories = NoneDict() def __init__(self, name, description="", logo_path=None, is_main_category=False, packages_requirements=None): self.name = name self.description = description self.logo_path = logo_path self.is_main_category = is_main_category self.default = None self.frameworks = NoneDict() self.packages_requirements = [] if packages_requirements is None else packages_requirements if self.prog_name in self.categories: logger.warning("There is already a registered category with {} as a name. Don't register the second one." .format(name)) else: self.categories[self.prog_name] = self @classproperty def main_category(self): for category in self.categories.values(): if category.is_main_category: return category return None @property def prog_name(self): """Get programmatic, path and CLI compatible names""" return self.name.lower().replace('/', '-').replace(' ', '-') @property def default_framework(self): """Get default framework""" for framework in self.frameworks.values(): if framework.is_category_default: return framework return None def register_framework(self, framework): """Register a new framework""" if framework.prog_name in self.frameworks: logger.error("There is already a registered framework with {} as a name. Don't register the second one." .format(framework.name)) else: self.frameworks[framework.prog_name] = framework @property def is_installed(self): """Return if the category is installed""" installed_frameworks = [framework for framework in self.frameworks.values() if framework.is_installed] if len(installed_frameworks) == 0: return self.NOT_INSTALLED if len(installed_frameworks) == len(self.frameworks): return self.FULLY_INSTALLED return self.PARTIALLY_INSTALLED def install_category_parser(self, parser): """Install category parser and get frameworks""" if not self.has_frameworks(): logging.debug("Skipping {} having no framework".format(self.name)) return # framework parser is directly category parser if self.is_main_category: framework_parser = parser else: self.category_parser = parser.add_parser(self.prog_name, help=self.description) framework_parser = self.category_parser.add_subparsers(dest="framework") for framework in self.frameworks.values(): framework.install_framework_parser(framework_parser) return framework_parser def has_frameworks(self): """Return if a category has at least one framework""" return len(self.frameworks) > 0 def has_one_framework(self): """Return if a category has one framework""" return len(self.frameworks) == 1 def run_for(self, args): """Running commands from args namespace""" # try to call default framework if any if not args.framework: if not self.default_framework: message = _("A default framework for category {} was requested where there is none".format(self.name)) logger.error(message) self.category_parser.print_usage() UI.return_main_screen(status_code=1) self.default_framework.run_for(args) return self.frameworks[args.framework].run_for(args) class BaseFramework(metaclass=abc.ABCMeta): def __init__(self, name, description, category, logo_path=None, is_category_default=False, install_path_dir=None, only_on_archs=None, only_ubuntu_version=None, packages_requirements=None, only_for_removal=False, expect_license=False, need_root_access=False): self.name = name self.description = description self.logo_path = None self.category = category self.is_category_default = is_category_default self.only_on_archs = [] if only_on_archs is None else only_on_archs self.only_ubuntu_version = [] if only_ubuntu_version is None else only_ubuntu_version self.packages_requirements = [] if packages_requirements is None else packages_requirements self.packages_requirements.extend(self.category.packages_requirements) self.only_for_removal = only_for_removal self.expect_license = expect_license # don't detect anything for completion mode (as we need to be quick), so avoid opening apt cache and detect # if it's installed. if is_completion_mode(): # only show it in shell completion if it was already installed if self.only_for_removal: config = ConfigHandler().config try: if not os.path.isdir(config["frameworks"][category.prog_name][self.prog_name]["path"]): # don't show the framework in shell completion as for removal only and not installed return except (TypeError, KeyError, FileNotFoundError): # don't show the framework in shell completion as for removal only and not installed return category.register_framework(self) return self.need_root_access = need_root_access if not need_root_access: with suppress(KeyError): self.need_root_access = not RequirementsHandler().is_bucket_installed(self.packages_requirements) if self.is_category_default: if self.category == BaseCategory.main_category: logger.error("Main category can't have default framework as {} requires".format(name)) self.is_category_default = False elif self.category.default_framework is not None: logger.error("Can't set {} as default for {}: this category already has a default framework ({}). " "Don't set any as default".format(category.name, name, self.category.default_framework.name)) self.is_category_default = False self.category.default_framework.is_category_default = False if not install_path_dir: install_path_dir = os.path.join("" if category.is_main_category else category.prog_name, self.prog_name) self.default_install_path = os.path.join(DEFAULT_INSTALL_TOOLS_PATH, install_path_dir) self.default_binary_link_path = DEFAULT_BINARY_LINK_PATH self.install_path = self.default_install_path # check if we have an install path previously set config = ConfigHandler().config try: self.install_path = config["frameworks"][category.prog_name][self.prog_name]["path"] except (TypeError, KeyError, FileNotFoundError): pass # This requires install_path and will register need_root or not if not self.is_installed and not self.is_installable: logger.info("Don't register {} as it's not installable on this configuration.".format(name)) return category.register_framework(self) @property def is_installable(self): """Return if the framework can be installed on that arch""" if self.only_for_removal: return False try: if len(self.only_on_archs) > 0: # we have some restricted archs, check we support it current_arch = get_current_arch() if current_arch not in self.only_on_archs: logger.debug("{} only supports {} archs and you are on {}.".format(self.name, self.only_on_archs, current_arch)) return False if len(self.only_ubuntu_version) > 0: current_version = get_current_ubuntu_version() if current_version not in self.only_ubuntu_version: logger.debug("{} only supports {} and you are on {}.".format(self.name, self.only_ubuntu_version, current_version)) return False if not RequirementsHandler().is_bucket_available(self.packages_requirements): return False except: logger.error("An error occurred when detecting platform, don't register {}".format(self.name)) return False return True @property def prog_name(self): """Get programmatic, path and CLI compatible names""" return self.name.lower().replace('/', '-').replace(' ', '-') @abc.abstractmethod def setup(self): """Method call to setup the Framework""" if not self.is_installable: logger.error(_("You can't install that framework on this machine")) UI.return_main_screen(status_code=1) if self.need_root_access and os.geteuid() != 0: logger.debug("Requesting root access") cmd = ["sudo", "-E", "env", "PATH={}".format(os.getenv("PATH"))] cmd.extend(sys.argv) MainLoop().quit(subprocess.call(cmd)) # be a normal, kind user as we don't want normal files to be written as root switch_to_current_user() @abc.abstractmethod def remove(self): """Method call to remove the current framework""" if not self.is_installed: logger.error(_("You can't remove {} as it isn't installed".format(self.name))) UI.return_main_screen(status_code=1) def mark_in_config(self): """Mark the installation as installed in the config file""" config = ConfigHandler().config config.setdefault("frameworks", {})\ .setdefault(self.category.prog_name, {})\ .setdefault(self.prog_name, {})["path"] = self.install_path ConfigHandler().config = config def remove_from_config(self): """Remove current framework from config""" config = ConfigHandler().config del(config["frameworks"][self.category.prog_name][self.prog_name]) ConfigHandler().config = config @property def is_installed(self): """Method call to know if the framework is installed""" if not os.path.isdir(self.install_path): return False if not RequirementsHandler().is_bucket_installed(self.packages_requirements): return False return True def install_framework_parser(self, parser): """Install framework parser""" this_framework_parser = parser.add_parser(self.prog_name, help=self.description) this_framework_parser.add_argument('destdir', nargs='?', help=_("If the default framework name isn't provided, " "destdir should contain a /")) this_framework_parser.add_argument('-r', '--remove', action="store_true", help=_("Remove framework if installed")) if self.expect_license: this_framework_parser.add_argument('--accept-license', dest="accept_license", action="store_true", help=_("Accept license without prompting")) return this_framework_parser def run_for(self, args): """Running commands from args namespace""" logger.debug("Call run_for on {}".format(self.name)) if args.remove: if args.destdir: message = "You can't specify a destination dir while removing a framework" logger.error(message) UI.return_main_screen(status_code=1) self.remove() else: install_path = None auto_accept_license = False if args.destdir: install_path = os.path.abspath(os.path.expanduser(args.destdir)) if self.expect_license and args.accept_license: auto_accept_license = True self.setup(install_path=install_path, auto_accept_license=auto_accept_license) class MainCategory(BaseCategory): def __init__(self): super().__init__(name="main", is_main_category=True) def _is_categoryclass(o): return inspect.isclass(o) and issubclass(o, BaseCategory) def _is_frameworkclass(o): """Filter concrete (non-abstract) subclasses of BaseFramework.""" return inspect.isclass(o) and issubclass(o, BaseFramework) and not inspect.isabstract(o) def load_module(module_abs_name, main_category): logger.debug("New framework module: {}".format(module_abs_name)) if module_abs_name not in sys.modules: import_module(module_abs_name) else: reload(sys.modules[module_abs_name]) module = sys.modules[module_abs_name] current_category = main_category # if no category found -> we assign to main category for category_name, CategoryClass in inspect.getmembers(module, _is_categoryclass): logger.debug("Found category: {}".format(category_name)) current_category = CategoryClass() # if we didn't register the category: escape the framework registration if current_category not in BaseCategory.categories.values(): return for framework_name, FrameworkClass in inspect.getmembers(module, _is_frameworkclass): if FrameworkClass(current_category) is not None: logger.debug("Attach framework {} to {}".format(framework_name, current_category.name)) def load_frameworks(): """Load all modules and assign to correct category""" main_category = MainCategory() # Prepare local paths (1. environment path, 2. local path, 3. system paths). # If we have duplicated categories, only consider the first loaded one. local_paths = [get_user_frameworks_path()] sys.path.insert(0, get_user_frameworks_path()) environment_path = os.environ.get(UMAKE_FRAMEWORKS_ENVIRON_VARIABLE) if environment_path: sys.path.insert(0, environment_path) local_paths.insert(0, environment_path) for loader, module_name, ispkg in pkgutil.iter_modules(path=local_paths): load_module(module_name, main_category) for loader, module_name, ispkg in pkgutil.iter_modules(path=[os.path.dirname(__file__)]): module_name = "{}.{}".format(__package__, module_name) load_module(module_name, main_category) ubuntu-make-16.11.1ubuntu1/umake/frameworks/__pycache__/0000755000000000000000000000000013135606406020026 5ustar ubuntu-make-16.11.1ubuntu1/umake/frameworks/games.py0000664000000000000000000003073413013560574017275 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014-2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Game IDEs module""" from concurrent import futures from contextlib import suppress from gettext import gettext as _ import logging import os import re import stat import json import umake.frameworks.baseinstaller from umake.network.download_center import DownloadItem from umake.tools import as_root, create_launcher, get_application_desktop_file, get_current_arch,\ ChecksumType, MainLoop, Checksum from umake.ui import UI logger = logging.getLogger(__name__) class GamesCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Games", description=_("Games Development Environment"), logo_path=None) class Stencyl(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Stencyl", description=_("Stencyl game developer IDE"), category=category, only_on_archs=['i386', 'amd64'], download_page="http://www.stencyl.com/download/", desktop_filename="stencyl.desktop", required_files_path=["Stencyl"], packages_requirements=["libxtst6:i386", "libxext6:i386", "libxi6:i386", "libncurses5:i386", "libxt6:i386", "libxpm4:i386", "libxmu6:i386", "libgtk2.0-0:i386", "libatk1.0-0:i386", "libc6:i386", "libcairo2:i386", "libexpat1:i386", "libfontconfig1:i386", "libfreetype6:i386", "libglib2.0-0:i386", "libice6:i386", "libpango1.0-0:i386", "libpng12-0:i386", "libsm6:i386", "libxau6:i386", "libxcursor1:i386", "libxdmcp6:i386", "libxfixes3:i386", "libx11-6:i386", "libxinerama1:i386", "libxrandr2:i386", "libxrender1:i386", "zlib1g:i386", "libnss3-1d:i386", "libnspr4-0d:i386", "libcurl3:i386", "libasound2:i386"]) def parse_download_link(self, line, in_download): """Parse Stencyl download links""" url, md5sum = (None, None) if ">Linux <" in line: in_download = True if in_download: regexp = r'href="(.*)"><.*64-' if get_current_arch() == "i386": regexp = r'href="(.*)"><.*32-' p = re.search(regexp, line) with suppress(AttributeError): url = p.group(1) if '


' in line: in_download = False if url is None: return (None, in_download) return ((url, None), in_download) def post_install(self): """Create the Stencyl launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Stencyl"), icon_path=os.path.join(self.install_path, "data", "other", "icon-30x30.png"), exec='"{}" %f'.format(self.exec_path), comment=self.description, categories="Development;IDE;", extra="Path={}\nStartupWMClass=stencyl-sw-Launcher".format(self.install_path))) def _chrome_sandbox_setuid(path): """Chown and setUID to chrome sandbox""" # switch to root with as_root(): try: os.chown(path, 0, -1) os.chmod(path, stat.S_ISUID | stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) logger.debug("Changed setUID mode {}".format(path)) return True except Exception as e: logger.error("Couldn't change owner and file perm to {}: {}".format(path, e)) return False class Unity3D(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Unity3d", description=_("Unity 3D Editor Linux experimental support"), category=category, only_on_archs=['amd64'], download_page="https://community.unity.com/t5/" + "Linux-Editor/Unity-on-Linux-Release-Notes-and-Known-Issues/m-p/2323665", match_last_link=True, checksum_type=ChecksumType.sha1, dir_to_decompress_in_tarball='unity-editor*', desktop_filename="unity3d-editor.desktop", required_files_path=[os.path.join("Editor", "Unity")], # we need root access for chrome sandbox setUID need_root_access=True, # Note that some packages requirements essential to the system itself are not listed (we # don't want to create fake packages and kill the container for medium tests) packages_requirements=[ "gconf-service", "lib32gcc1", "lib32stdc++6", "libasound2", "libcairo2", "libcap2", "libcups2", "libfontconfig1", "libfreetype6", "libgconf-2-4", "libgdk-pixbuf2.0-0", "libglu1-mesa", "libgtk2.0-0", "libgl1-mesa-glx | libgl1-mesa-glx-lts-utopic |\ libgl1-mesa-glx-lts-vivid | libgl1-mesa-glx-lts-wily", "libnspr4", "libnss3", "libpango1.0-0", "libpq5", "libxcomposite1", "libxcursor1", "libxdamage1", "libxext6", "libxfixes3", "libxi6", "libxrandr2", "libxrender1", "libxtst6", "monodevelop"]) # monodevelop is for mono deps, temporary def parse_download_link(self, line, in_download): """Parse Unity3d download links""" url, sha1 = (None, None) if ".sh" in line: in_download = True p = re.search(r'.deb.*.href="(.*.sh)"', line) with suppress(AttributeError): url = p.group(1) if in_download is True: p = re.search(r'sha1sum (\w+)\)

Torrent', line) with suppress(AttributeError): sha1 = p.group(1) return ((url, sha1), in_download) def decompress_and_install(self, fds): """Override to strip the unwanted shell header part""" logger.debug("Start looking at the archive inside the script") for line in fds[0]: if line.startswith(b"__ARCHIVE_BEGINS_HERE__"): logger.debug("Found the archive inside the script") break super().decompress_and_install(fds) def post_install(self): """Create the Unity 3D launcher and setuid chrome sandbox""" with futures.ProcessPoolExecutor(max_workers=1) as executor: # chrome sandbox requires this: https//code.google.com/p/chromium/wiki/LinuxSUIDSandbox f = executor.submit(_chrome_sandbox_setuid, os.path.join(self.install_path, "Editor", "chrome-sandbox")) if not f.result(): UI.return_main_screen(exit_status=1) create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Unity3D Editor"), icon_path=os.path.join(self.install_path, "unity-editor-icon.png"), exec=self.exec_path, comment=self.description, categories="Development;IDE;")) class Twine(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Twine", description=_("Twine tool for creating interactive and nonlinear stories"), category=category, only_on_archs=['i386', 'amd64'], download_page="http://twinery.org/", dir_to_decompress_in_tarball='twine*', desktop_filename="twine.desktop", required_files_path=["Twine"]) # add logo download as the tar doesn't provide one self.download_requests.append(DownloadItem("http://twinery.org/img/logo.svg", None)) def parse_download_link(self, line, in_download): """Parse Twine download links""" url = None regexp = r'href="(.*)" .*linux64' if get_current_arch() == "i386": regexp = r'href="(.*)" .*linux32' p = re.search(regexp, line) with suppress(AttributeError): url = p.group(1) return ((url, None), False) def decompress_and_install(self, fds): # if icon, we grab the icon name to reference it later on for fd in fds: if fd.name.endswith(".svg"): orig_icon_name = os.path.basename(fd.name) break else: logger.error("We couldn't download the Twine icon") UI.return_main_screen(exit_status=1) super().decompress_and_install(fds) # rename the asset logo self.icon_name = "logo.svg" os.rename(os.path.join(self.install_path, orig_icon_name), os.path.join(self.install_path, self.icon_name)) def post_install(self): """Create the Twine launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Twine"), icon_path=os.path.join(self.install_path, self.icon_name), exec='"{}" %f'.format(self.exec_path), comment=self.description, categories="Development;IDE;")) class Superpowers(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Superpowers", description=_("The HTML5 2D+3D game maker"), category=category, only_on_archs=['i386', 'amd64'], download_page="https://api.github.com/repos/superpowers/superpowers-app/releases/latest", dir_to_decompress_in_tarball='superpowers*', desktop_filename="superpowers.desktop", required_files_path=["Superpowers"]) arch_trans = { "amd64": "x64", "i386": "ia32" } @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): logger.debug("Fetched download page, parsing.") page = result[self.download_page] error_msg = page.error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) try: assets = json.loads(page.buffer.read().decode())["assets"] download_url = None for asset in assets: if "linux-{}".format(self.arch_trans[get_current_arch()]) in asset["browser_download_url"]: download_url = asset["browser_download_url"] if not download_url: raise IndexError except (json.JSONDecodeError, IndexError): logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) logger.debug("Found download URL: " + download_url) self.download_requests.append(DownloadItem(download_url, None)) self.start_download_and_install() def post_install(self): """Create the Superpowers launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Superpowers"), icon_path=os.path.join(self.install_path, "resources", "app", "renderer", "images", "superpowers-256.png"), exec='"{}" %f'.format(self.exec_path), comment=self.description, categories="Development;IDE;")) ubuntu-make-16.11.1ubuntu1/umake/frameworks/swift.py0000664000000000000000000001436413013560574017336 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Swift module""" from contextlib import suppress from gettext import gettext as _ import gnupg import logging import os import re import tempfile import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.tools import add_env_to_user, as_root, MainLoop, get_current_ubuntu_version from umake.network.download_center import DownloadCenter, DownloadItem from umake.ui import UI logger = logging.getLogger(__name__) class SwiftCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Swift", description=_("Swift language"), logo_path=None) class SwiftLang(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Swift Lang", description=_("Swift compiler (default)"), is_category_default=True, packages_requirements=["clang", "libicu-dev"], category=category, only_on_archs=['amd64'], download_page="https://swift.org/download/", dir_to_decompress_in_tarball="swift*", required_files_path=[os.path.join("usr", "bin", "swift")]) self.asc_url = "https://swift.org/keys/all-keys.asc" def parse_download_link(self, line, in_download): """Parse Swift download link, expect to find a .sig file""" sig_url = None if '.tar.gz.sig' in line: in_download = True if in_download: p = re.search(r'href="(.*)" title="PGP Signature"', line) with suppress(AttributeError): sig_url = "https://swift.org" + p.group(1) logger.debug("Found signature link: {}".format(sig_url)) return (sig_url, in_download) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): """Download files to download + license and check it""" logger.debug("Parse download metadata") error_msg = result[self.download_page].error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) in_download = False sig_url = None for line in result[self.download_page].buffer: line_content = line.decode() (new_sig_url, in_download) = self.parse_download_link(line_content, in_download) if str(new_sig_url) > str(sig_url): tmp_release = re.search("ubuntu(.....).tar", new_sig_url).group(1) if tmp_release <= get_current_ubuntu_version(): sig_url = new_sig_url if not sig_url: logger.error("Download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) DownloadCenter(urls=[DownloadItem(sig_url, None), DownloadItem(self.asc_url, None)], on_done=self.check_gpg_and_start_download, download=False) def _check_gpg_signature(self, gnupgdir, asc_content, sig): """check gpg signature (temporary stock in dir)""" gpg = gnupg.GPG(gnupghome=gnupgdir) imported_keys = gpg.import_keys(asc_content) if imported_keys.count == 0: logger.error("Keys not valid") UI.return_main_screen(status_code=1) verify = gpg.verify(sig) if verify is False: logger.error("Signature not valid") UI.return_main_screen(status_code=1) @MainLoop.in_mainloop_thread def check_gpg_and_start_download(self, download_result): asc_content = download_result.pop(self.asc_url).buffer.getvalue().decode('utf-8') sig_url = list(download_result.keys())[0] res = download_result[sig_url] sig = res.buffer.getvalue().decode('utf-8').split()[0] # When we install new packages, we are executing as root and then dropping # as the user for extracting and such. However, for signature verification, # we use gpg. This one doesn't like priviledge drop (if uid = 0 and # euid = 1000) and asserts if uid != euid. # Importing the key as root as well creates new gnupg files owned as root if # new keys weren't imported first. # Consequently, run gpg as root if we needed root access or as the user # otherwise. We store the gpg public key in a temporary gnupg directory that # will be removed under the same user rights (this directory needs to be owned # by the same user id to not be rejected by gpg).Z if self.need_root_access: with as_root(): with tempfile.TemporaryDirectory() as tmpdirname: self._check_gpg_signature(tmpdirname, asc_content, sig) else: with tempfile.TemporaryDirectory() as tmpdirname: self._check_gpg_signature(tmpdirname, asc_content, sig) # you get and store self.download_url url = re.sub('.sig', '', sig_url) if url is None: logger.error("Download page changed its syntax or is not parsable (missing url)") UI.return_main_screen(status_code=1) logger.debug("Found download link for {}".format(url)) self.download_requests.append(DownloadItem(url, None)) self.start_download_and_install() def post_install(self): """Add swift necessary env variables""" add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "usr", "bin")}}) UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name))) ubuntu-make-16.11.1ubuntu1/umake/frameworks/baseinstaller.py0000664000000000000000000004526213013560574021033 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Downloader abstract module""" from contextlib import suppress from gettext import gettext as _ from io import StringIO import logging from progressbar import ProgressBar import os import shutil import umake.frameworks from umake.decompressor import Decompressor from umake.interactions import InputText, YesNo, LicenseAgreement, DisplayMessage, UnknownProgress from umake.network.download_center import DownloadCenter, DownloadItem from umake.network.requirements_handler import RequirementsHandler from umake.ui import UI from umake.tools import MainLoop, strip_tags, launcher_exists, get_icon_path, get_launcher_path, \ Checksum, remove_framework_envs_from_user, add_exec_link logger = logging.getLogger(__name__) class BaseInstaller(umake.frameworks.BaseFramework): DIRECT_COPY_EXT = ['.svg', '.png', '.ico', '.jpg', '.jpeg'] # Framework environment variables are added to `~/.profile` which may # require logging back into your session for the changes to be picked up. # Use `RELOGIN_REQUIRE_MSG` to alert users to this fact, in `post_install` # function. {} in replaced with the framework name at runtime. RELOGIN_REQUIRE_MSG = _("You may need to log back in for your {} installation to work properly") def __new__(cls, *args, **kwargs): "This class is not meant to be instantiated, so __new__ returns None." if cls == BaseInstaller: return None return super().__new__(cls) def __init__(self, *args, **kwargs): """The Downloader framework isn't instantiated directly, but is useful to inherit from for all frameworks having a set of downloads to proceed, some eventual supported_archs.""" self.download_page = kwargs["download_page"] self.checksum_type = kwargs.get("checksum_type", None) self.dir_to_decompress_in_tarball = kwargs.get("dir_to_decompress_in_tarball", "") self.required_files_path = kwargs.get("required_files_path", []) self.desktop_filename = kwargs.get("desktop_filename", None) self.icon_filename = kwargs.get("icon_filename", None) self.match_last_link = kwargs.get("match_last_link", False) for extra_arg in ["download_page", "checksum_type", "dir_to_decompress_in_tarball", "desktop_filename", "icon_filename", "required_files_path", "match_last_link"]: with suppress(KeyError): kwargs.pop(extra_arg) super().__init__(*args, **kwargs) self._install_done = False self._paths_to_clean = set() self._arg_install_path = None self.download_requests = [] @property def exec_link_name(self): if self.desktop_filename: return self.desktop_filename.split('.')[0] return None @property def is_installed(self): # check path and requirements if not super().is_installed: return False for required_file_path in self.required_files_path: if not os.path.exists(os.path.join(self.install_path, required_file_path)): logger.debug("{} binary isn't installed".format(self.name)) return False if self.desktop_filename: return launcher_exists(self.desktop_filename) logger.debug("{} is installed".format(self.name)) return True def setup(self, install_path=None, auto_accept_license=False): self.arg_install_path = install_path self.auto_accept_license = auto_accept_license super().setup() # first step, check if installed if self.is_installed: UI.display(YesNo("{} is already installed on your system, do you want to reinstall " "it anyway?".format(self.name), self.reinstall, UI.return_main_screen)) else: self.confirm_path(self.arg_install_path) def reinstall(self): logger.debug("Mark previous installation path for cleaning.") self._paths_to_clean.add(self.install_path) # remove previous installation path self.confirm_path(self.arg_install_path) remove_framework_envs_from_user(self.name) def remove(self): """Remove current framework if installed Not that we only remove desktop file, launcher icon and dir content, we do not remove packages as they might be in used for other framework""" # check if it's installed and so on. super().remove() UI.display(DisplayMessage("Removing {}".format(self.name))) if self.desktop_filename: with suppress(FileNotFoundError): os.remove(get_launcher_path(self.desktop_filename)) os.remove(os.path.join(self.default_binary_link_path, self.exec_link_name)) if self.icon_filename: with suppress(FileNotFoundError): os.remove(get_icon_path(self.icon_filename)) with suppress(FileNotFoundError): shutil.rmtree(self.install_path) remove_framework_envs_from_user(self.name) self.remove_from_config() UI.delayed_display(DisplayMessage("Suppression done")) UI.return_main_screen() def confirm_path(self, path_dir=""): """Confirm path dir""" if not path_dir: logger.debug("No installation path provided. Requesting one.") UI.display(InputText("Choose installation path:", self.confirm_path, self.install_path)) return logger.debug("Installation path provided. Checking if exists.") with suppress(FileNotFoundError): if os.listdir(path_dir): # we already told we were ok to overwrite as it was the previous install path if path_dir not in self._paths_to_clean: if path_dir == "/": logger.error("This doesn't seem wise. We won't let you shoot in your feet.") self.confirm_path() return self.install_path = path_dir # we don't set it before to not repropose / as installation path UI.display(YesNo("{} isn't an empty directory, do you want to remove its content and install " "there?".format(path_dir), self.set_installdir_to_clean, UI.return_main_screen)) return self.install_path = path_dir if self.desktop_filename: self.exec_path = os.path.join(self.install_path, self.required_files_path[0]) self.download_provider_page() def set_installdir_to_clean(self): logger.debug("Mark non empty new installation path for cleaning.") self._paths_to_clean.add(self.install_path) self.download_provider_page() def download_provider_page(self): logger.debug("Download application provider page") DownloadCenter([DownloadItem(self.download_page)], self.get_metadata_and_check_license, download=False) def parse_license(self, line, license_txt, in_license): """Parse license per line, eventually write to license_txt if it's in the license part. A flag in_license that is returned by the same function helps to decide if we are in the license part""" pass def parse_download_link(self, line, in_download): """Parse download_link per line. in_download is a helper that the function return to know if it's in the download part. return a tuple of (None, in_download=True/False) if no parsable is found or ((url, md5sum), in_download=True/False)""" pass @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): """Download files to download + license and check it""" logger.debug("Parse download metadata") error_msg = result[self.download_page].error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) url, checksum = (None, None) with StringIO() as license_txt: in_license = False in_download = False for line in result[self.download_page].buffer: line_content = line.decode() if self.expect_license and not self.auto_accept_license: in_license = self.parse_license(line_content, license_txt, in_license) # always take the first valid (url, checksum) if not match_last_link is set to True: download = None if url is None or (self.checksum_type and not checksum) or self.match_last_link: (download, in_download) = self.parse_download_link(line_content, in_download) if download is not None: (newurl, new_checksum) = download url = newurl if newurl is not None else url checksum = new_checksum if new_checksum is not None else checksum if url is not None: if self.checksum_type and checksum: logger.debug("Found download link for {}, checksum: {}".format(url, checksum)) elif not self.checksum_type: logger.debug("Found download link for {}".format(url)) if url is None: logger.error("Download page changed its syntax or is not parsable (url missing)") UI.return_main_screen(status_code=1) if (self.checksum_type and checksum is None): logger.error("Download page changed its syntax or is not parsable (checksum missing)") logger.error("URL is: {}".format(url)) UI.return_main_screen(status_code=1) self.download_requests.append(DownloadItem(url, Checksum(self.checksum_type, checksum))) if license_txt.getvalue() != "": logger.debug("Check license agreement.") UI.display(LicenseAgreement(strip_tags(license_txt.getvalue()).strip(), self.start_download_and_install, UI.return_main_screen)) elif self.expect_license and not self.auto_accept_license: logger.error("We were expecting to find a license on the download page, we didn't.") UI.return_main_screen(status_code=1) else: self.start_download_and_install() def start_download_and_install(self): self.last_progress_download = None self.last_progress_requirement = None self.balance_requirement_download = None self.pkg_size_download = 0 self.result_requirement = None self.result_download = None self._download_done_callback_called = False UI.display(DisplayMessage("Downloading and installing requirements")) self.pbar = ProgressBar().start() self.pkg_to_install = RequirementsHandler().install_bucket(self.packages_requirements, self.get_progress_requirement, self.requirement_done) DownloadCenter(urls=self.download_requests, on_done=self.download_done, report=self.get_progress_download) @MainLoop.in_mainloop_thread def get_progress(self, progress_download, progress_requirement): """Global progress info. Don't use named parameters as idle_add doesn't like it""" if progress_download is not None: self.last_progress_download = progress_download if progress_requirement is not None: self.last_progress_requirement = progress_requirement # we wait to have the file size to start getting progress proportion info # try to compute balance requirement if self.balance_requirement_download is None: if not self.pkg_to_install: self.balance_requirement_download = 0 self.last_progress_requirement = 0 if self.last_progress_download is None: return else: # we only update if we got a progress from both sides if self.last_progress_download is None or self.last_progress_requirement is None: return else: # apply a minimum of 15% (no download or small download + install time) self.balance_requirement_download = max(self.pkg_size_download / (self.pkg_size_download + self.total_download_size), 0.15) if not self.pbar.finished: # drawing is delayed, so ensure we are not done first progress = self._calculate_progress() self.pbar.update(progress) def _calculate_progress(self): progress = self.balance_requirement_download * self.last_progress_requirement +\ (1 - self.balance_requirement_download) * self.last_progress_download normalized_progress = max(0, progress) normalized_progress = min(normalized_progress, 100) return normalized_progress def get_progress_requirement(self, status): """Chain up to main get_progress, returning current value between 0 and 100""" percentage = status["percentage"] # 60% is download, 40% is installing if status["step"] == RequirementsHandler.STATUS_DOWNLOADING: self.pkg_size_download = status["pkg_size_download"] progress = 0.6 * percentage else: if self.pkg_size_download == 0: progress = percentage # no download, only install else: progress = 60 + 0.4 * percentage self.get_progress(None, progress) def get_progress_download(self, downloads): """Chain up to main get_progress, returning current value between 0 and 100 First call initialize the balance between requirements and download progress""" # don't push any progress until we have the total download size if len(downloads) != len(self.download_requests): return total_size = 0 total_current_size = 0 for download in downloads: total_size += downloads[download]["size"] total_current_size += downloads[download]["current"] self.total_download_size = total_size self.get_progress(total_current_size / total_size * 100, None) def requirement_done(self, result): # set requirement download as finished if no error if not result.error: self.get_progress(None, 100) self.result_requirement = result self.download_and_requirements_done() def download_done(self, result): # set download as finished if no error for url in result: if result[url].error: break else: self.get_progress(100, None) self.result_download = result self.download_and_requirements_done() @MainLoop.in_mainloop_thread def download_and_requirements_done(self): # wait for both side to be done if self._download_done_callback_called or (not self.result_download or not self.result_requirement): return self._download_done_callback_called = True self.pbar.finish() # display eventual errors error_detected = False if self.result_requirement.error: logger.error("Package requirements can't be met: {}".format(self.result_requirement.error)) error_detected = True # check for any errors and collect fds fds = [] for url in self.result_download: if self.result_download[url].error: logger.error(self.result_download[url].error) error_detected = True fds.append(self.result_download[url].fd) if error_detected: UI.return_main_screen(status_code=1) # now decompress self.decompress_and_install(fds) def decompress_and_install(self, fds): UI.display(DisplayMessage("Installing {}".format(self.name))) # empty destination directory if reinstall for dir_to_remove in self._paths_to_clean: with suppress(FileNotFoundError): shutil.rmtree(dir_to_remove) # marked them as cleaned self._paths_to_clean = [] os.makedirs(self.install_path, exist_ok=True) decompress_fds = {} for fd in fds: direct_copy = False for ext in self.DIRECT_COPY_EXT: if fd.name.endswith(ext): direct_copy = True break if direct_copy: shutil.copy2(fd.name, os.path.join(self.install_path, os.path.basename(fd.name))) else: decompress_fds[fd] = Decompressor.DecompressOrder(dir=self.dir_to_decompress_in_tarball, dest=self.install_path) Decompressor(decompress_fds, self.decompress_and_install_done) UI.display(UnknownProgress(self.iterate_until_install_done)) def post_install(self): """Call the post_install process, like creating a launcher, adding env variables…""" pass @MainLoop.in_mainloop_thread def decompress_and_install_done(self, result): self._install_done = True error_detected = False for fd in result: if result[fd].error: logger.error(result[fd].error) error_detected = True fd.close() if error_detected: UI.return_main_screen(status_code=1) self.post_install() if self.exec_link_name: add_exec_link(self.exec_path, self.exec_link_name) # Mark as installation done in configuration self.mark_in_config() UI.delayed_display(DisplayMessage("Installation done")) UI.return_main_screen() def iterate_until_install_done(self): while not self._install_done: yield ubuntu-make-16.11.1ubuntu1/umake/frameworks/kotlin.py0000664000000000000000000000570713013560574017503 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2016 Canonical # # Authors: # Omer Sheikh # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Kotlin module""" from gettext import gettext as _ import logging import os import json import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.tools import add_env_to_user, MainLoop from umake.ui import UI from umake.network.download_center import DownloadItem logger = logging.getLogger(__name__) class KotlinCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Kotlin", description=_("The Kotlin Programming Language"), logo_path=None) class KotlinLang(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Kotlin Lang", description=_("Kotlin language standalone compiler"), is_category_default=True, category=category, packages_requirements=["openjdk-7-jre | openjdk-8-jre"], download_page="https://api.github.com/repos/Jetbrains/kotlin/releases/latest", dir_to_decompress_in_tarball="kotlinc", required_files_path=[os.path.join("bin", "kotlinc")]) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): logger.debug("Fetched download page, parsing.") page = result[self.download_page] error_msg = page.error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) try: assets = json.loads(page.buffer.read().decode())["assets"] download_url = assets[0]["browser_download_url"] except (json.JSONDecodeError, IndexError): logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) logger.debug("Found download URL: " + download_url) self.download_requests.append(DownloadItem(download_url, None)) self.start_download_and_install() def post_install(self): """Add the Kotlin binary dir to PATH""" add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "bin")}}) UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name))) ubuntu-make-16.11.1ubuntu1/umake/frameworks/rust.py0000664000000000000000000001321113013560574017165 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Tin Tvrtković # Jared Ravetch # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Rust module""" from contextlib import suppress from gettext import gettext as _ from glob import glob import logging import os import re from bs4 import BeautifulSoup import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.network.download_center import DownloadItem, DownloadCenter from umake.tools import get_current_arch, add_env_to_user, ChecksumType, \ MainLoop, Checksum from umake.ui import UI logger = logging.getLogger(__name__) class RustCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Rust", description=_("Rust language"), logo_path=None) class RustLang(umake.frameworks.baseinstaller.BaseInstaller): # Button labels on the download page. arch_trans = { "amd64": "64-bit", "i386": "32-bit" } def __init__(self, category): super().__init__(name="Rust Lang", description=_("The official Rust distribution"), is_category_default=True, category=category, only_on_archs=['i386', 'amd64'], download_page="https://www.rust-lang.org/en-US/downloads.html", checksum_type=ChecksumType.sha256, dir_to_decompress_in_tarball="rust-*") def parse_download_link(self, line, in_download): """Parse Rust download link, expect to find a url""" url, sha1 = (None, None) arch = get_current_arch() if "{}-unknown-linux-gnu.tar.gz".format(self.arch_trans[arch]) in line: in_download = True if in_download: p = re.search(r'href="(.*)">', line) with suppress(AttributeError): url = p.group(1) p = re.search(r'(\w+)', line) with suppress(AttributeError): sha1 = p.group(1) if "" in line: in_download = False if url is None and sha1 is None: return (None, in_download) return ((url, sha1), in_download) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): """Override this so we can use BS and fetch the checksum separately.""" logger.debug("Fetched download page, parsing.") page = result[self.download_page] error_msg = page.error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page_url, error_msg)) UI.return_main_screen(status_code=1) soup = BeautifulSoup(page.buffer, 'html.parser') link = (soup.find('div', class_="install") .find('td', class_="inst-type", text="Linux (.tar.gz)") .parent .find(text=self.arch_trans[get_current_arch()]) .parent .parent) if link is None: logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) download_url = link.attrs['href'] checksum_url = download_url + '.sha256' logger.debug("Found download URL: " + download_url) logger.debug("Downloading checksum first, from " + checksum_url) def checksum_downloaded(results): checksum_result = next(iter(results.values())) # Just get the first. if checksum_result.error: logger.error(checksum_result.error) UI.return_main_screen(status_code=1) checksum = checksum_result.buffer.getvalue().decode('utf-8').split()[0] logger.info('Obtained SHA256 checksum: ' + checksum) self.download_requests.append(DownloadItem(download_url, checksum=Checksum(ChecksumType.sha256, checksum), ignore_encoding=True)) self.start_download_and_install() DownloadCenter([DownloadItem(checksum_url)], on_done=checksum_downloaded, download=False) def post_install(self): """Add rust necessary env variables""" add_env_to_user(self.name, {"PATH": {"value": "{}:{}".format(os.path.join(self.install_path, "rustc", "bin"), os.path.join(self.install_path, "cargo", "bin"))}, "LD_LIBRARY_PATH": {"value": os.path.join(self.install_path, "rustc", "lib")}}) # adjust for rust 1.5 some symlinks magic to have stdlib craft available os.chdir(os.path.join(self.install_path, "rustc", "lib")) os.rename("rustlib", "rustlib.init") os.symlink(glob(os.path.join('..', '..', 'rust-std-*', 'lib', 'rustlib'))[0], 'rustlib') os.symlink(os.path.join('..', 'rustlib.init', 'etc'), os.path.join('rustlib', 'etc')) UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name))) ubuntu-make-16.11.1ubuntu1/umake/frameworks/go.py0000664000000000000000000000550013013560574016577 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Go module""" from contextlib import suppress from gettext import gettext as _ import logging import os import re import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.tools import get_current_arch, add_env_to_user, ChecksumType from umake.ui import UI logger = logging.getLogger(__name__) class GoCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Go", description=_("Go language"), logo_path=None) class GoLang(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Go Lang", description=_("Google compiler (default)"), is_category_default=True, category=category, only_on_archs=['i386', 'amd64'], download_page="https://golang.org/dl/", checksum_type=ChecksumType.sha256, dir_to_decompress_in_tarball="go", required_files_path=[os.path.join("bin", "go")]) def parse_download_link(self, line, in_download): """Parse Go download link, expect to find a sha and a url""" url, sha = (None, None) if "linux-{}".format(get_current_arch().replace("i386", "386")) in line: in_download = True if in_download: p = re.search(r'href="(.*)">', line) with suppress(AttributeError): url = p.group(1) p = re.search(r'(\w+)', line) with suppress(AttributeError): sha = p.group(1) if "" in line: in_download = False if url is None and sha is None: return (None, in_download) return ((url, sha), in_download) def post_install(self): """Add go necessary env variables""" add_env_to_user(self.name, {"PATH": {"value": os.path.join(self.install_path, "bin")}, "GOROOT": {"value": self.install_path, "keep": False}}) UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name))) ubuntu-make-16.11.1ubuntu1/umake/frameworks/android.py0000664000000000000000000002043213013560574017613 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Android module""" from contextlib import suppress from gettext import gettext as _ import logging import os import platform import re import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.ui import UI from umake.tools import add_env_to_user, create_launcher, get_application_desktop_file, ChecksumType logger = logging.getLogger(__name__) _supported_archs = ['i386', 'amd64'] class AndroidCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Android", description=_("Android Development Environment"), logo_path=None) def parse_license(self, tag, line, license_txt, in_license): """Parse Android download page for license""" if line.startswith(tag): in_license = True if in_license: if line.startswith('
'): in_license = False else: license_txt.write(line) return in_license def parse_download_link(self, tag, line, in_download): """Parse Android download links, expect to find a sha1sum and a url""" url, sha1sum = (None, None) if tag in line: in_download = True if in_download: p = re.search(r'href="(.*)"', line) with suppress(AttributeError): url = p.group(1) p = re.search(r'(\w+)', line) with suppress(AttributeError): # ensure the size can match a md5 or sha1 checksum if len(p.group(1)) > 15: sha1sum = p.group(1) if "" in line: in_download = False if url is None and sha1sum is None: return (None, in_download) if url and url.startswith("//"): url = "https:" + url return ((url, sha1sum), in_download) class AndroidStudio(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Android Studio", description=_("Android Studio (default)"), is_category_default=True, category=category, only_on_archs=_supported_archs, expect_license=True, packages_requirements=["openjdk-7-jdk | openjdk-8-jdk", "libncurses5:i386", "libstdc++6:i386", "zlib1g:i386"], download_page="https://developer.android.com/sdk/index.html", checksum_type=ChecksumType.sha1, dir_to_decompress_in_tarball="android-studio", desktop_filename="android-studio.desktop", required_files_path=[os.path.join("bin", "studio.sh")]) def parse_license(self, line, license_txt, in_license): """Parse Android Studio download page for license""" return self.category.parse_license('
Linux ', line, in_download) def post_install(self): """Add necessary environment variables""" add_env_to_user(self.name, {"NDK_ROOT": {"value": self.install_path, "keep": False}}) # print wiki page message UI.display(DisplayMessage("NDK installed in {}. More information on how to use it on {}".format( self.install_path, "https://developer.android.com/tools/sdk/ndk/index.html#GetStarted"))) class EclipseADTForRemoval(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Eclipse ADT", description="For removal only (not supported upstream anymore)", download_page=None, category=category, only_on_archs=_supported_archs, only_for_removal=True) ubuntu-make-16.11.1ubuntu1/umake/frameworks/nodejs.py0000664000000000000000000000764613013560574017471 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Nodejs module""" from contextlib import suppress from gettext import gettext as _ import logging import os import subprocess import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage from umake.tools import get_current_arch, add_env_to_user, ChecksumType from umake.ui import UI logger = logging.getLogger(__name__) class NodejsCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Nodejs", description=_("Nodejs stable"), logo_path=None) class NodejsLang(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Nodejs Lang", description=_("Nodejs stable"), is_category_default=True, category=category, only_on_archs=['i386', 'amd64'], download_page="https://nodejs.org/dist/latest/SHASUMS256.txt", checksum_type=ChecksumType.sha256, dir_to_decompress_in_tarball="node*", required_files_path=[os.path.join("bin", "node")]) arch_trans = { "amd64": "x64", "i386": "x86" } def parse_download_link(self, line, in_download): """Parse Nodejs download link, expect to find a sha1 and a url""" url, shasum = (None, None) arch = get_current_arch() if "linux-{}.tar.xz".format(self.arch_trans[arch]) in line: in_download = True if in_download: url = self.download_page.strip("SHASUMS256.txt") + line.split(' ')[2].rstrip() shasum = line.split(' ')[0] if url is None and shasum is None: return (None, in_download) return ((url, shasum), in_download) def prefix_set(self): with suppress(IOError): with open('{}/.npmrc'.format(os.path.expanduser('~')), 'r') as file: for line in file.readlines(): if line.startswith("prefix ="): return True return False def post_install(self): """Add nodejs necessary env variables and move module folder""" if not self.prefix_set(): with open('{}/.npmrc'.format(os.path.expanduser('~')), 'a+') as file: file.write("prefix = ${HOME}/.npm_modules") add_env_to_user(self.name, {"PATH": {"value": "{}:{}".format(os.path.join(self.install_path, "bin"), os.path.join(os.path.expanduser('~'), ".npm_modules", "bin"))}}) UI.delayed_display(DisplayMessage(self.RELOGIN_REQUIRE_MSG.format(self.name))) def install_framework_parser(self, parser): this_framework_parser = super().install_framework_parser(parser) this_framework_parser.add_argument('--lts', action="store_true", help=_("Install lts version")) return this_framework_parser def run_for(self, args): if args.lts: self.download_page = "https://nodejs.org/dist/latest-argon/SHASUMS256.txt" print('Download from {}'.format(self.download_page)) super().run_for(args) ubuntu-make-16.11.1ubuntu1/umake/frameworks/ide.py0000664000000000000000000012430013013560574016733 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014-2015 Canonical # # Authors: # Didier Roche # Tin Tvrtković # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Generic IDE module.""" from abc import ABCMeta, abstractmethod from bs4 import BeautifulSoup from concurrent import futures from contextlib import suppress from gettext import gettext as _ import grp from io import StringIO import json import logging import os from os.path import join import pwd import platform import re import subprocess from urllib import parse import shutil import umake.frameworks.baseinstaller from umake.interactions import DisplayMessage, LicenseAgreement from umake.network.download_center import DownloadCenter, DownloadItem from umake.tools import as_root, create_launcher, get_application_desktop_file, ChecksumType, Checksum, MainLoop,\ strip_tags, add_env_to_user, add_exec_link, get_current_arch from umake.ui import UI logger = logging.getLogger(__name__) def _add_to_group(user, group): """Add user to group""" # switch to root with as_root(): try: output = subprocess.check_output(["adduser", user, group]) logger.debug("Added {} to {}: {}".format(user, group, output)) return True except subprocess.CalledProcessError as e: logger.error("Couldn't add {} to {}".format(user, group)) return False class IdeCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="IDE", description=_("Generic IDEs"), logo_path=None) class BaseEclipse(umake.frameworks.baseinstaller.BaseInstaller, metaclass=ABCMeta): """The Eclipse Foundation distribution.""" def __init__(self, *args, **kwargs): if self.executable: current_required_files_path = kwargs.get("required_files_path", []) current_required_files_path.append(os.path.join(self.executable)) kwargs["required_files_path"] = current_required_files_path download_page = 'https://www.eclipse.org/downloads/eclipse-packages/' kwargs["download_page"] = download_page super().__init__(*args, **kwargs) self.icon_url = os.path.join("https://www.eclipse.org/downloads/", "images", self.icon_filename) self.bits = '' if platform.machine() == 'i686' else 'x86_64' self.headers = {'User-agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu " "Chromium/41.0.2272.76 Chrome/41.0.2272.76 Safari/537.36"} @property @abstractmethod def download_keyword(self): pass @property @abstractmethod def executable(self): pass def download_provider_page(self): logger.debug("Download application provider page") DownloadCenter([DownloadItem(self.download_page, headers=self.headers)], self.get_metadata, download=False) def parse_download_link(self, line, in_download): """Parse Eclipse download links""" url_found = False if self.download_keyword in line and self.bits in line: in_download = True else: in_download = False if in_download: p = re.search(r'href="(.*)" title', line) with suppress(AttributeError): self.sha512_url = "https://www.eclipse.org/" + p.group(1) + '.sha512&r=1' url_found = True DownloadCenter(urls=[DownloadItem(self.sha512_url, None)], on_done=self.get_sha_and_start_download, download=False) return (url_found, in_download) @MainLoop.in_mainloop_thread def get_metadata(self, result): """Download files to download + license and check it""" logger.debug("Parse download metadata") error_msg = result[self.download_page].error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) in_download = False url_found = False for line in result[self.download_page].buffer: line_content = line.decode() (_url_found, in_download) = self.parse_download_link(line_content, in_download) if not url_found: url_found = _url_found if not url_found: logger.error("Download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) @MainLoop.in_mainloop_thread def get_sha_and_start_download(self, download_result): res = download_result[self.sha512_url] sha512 = res.buffer.getvalue().decode('utf-8').split()[0] # you get and store self.download_url url = re.sub('.sha512', '', self.sha512_url) if url is None: logger.error("Download page changed its syntax or is not parsable (missing url)") UI.return_main_screen(status_code=1) if sha512 is None: logger.error("Download page changed its syntax or is not parsable (missing sha512)") UI.return_main_screen(status_code=1) logger.debug("Found download link for {}, checksum: {}".format(url, sha512)) self.download_requests.append(DownloadItem(url, Checksum(ChecksumType.sha512, sha512))) self.start_download_and_install() def post_install(self): """Create the Eclipse launcher""" DownloadCenter(urls=[DownloadItem(self.icon_url, None)], on_done=self.save_icon, download=True) icon_path = join(self.install_path, self.icon_filename) comment = self.description categories = "Development;IDE;" create_launcher(self.desktop_filename, get_application_desktop_file(name=self.name, icon_path=icon_path, exec='"{}" %f'.format(self.exec_path), comment=comment, categories=categories)) def save_icon(self, download_result): """Save correct Eclipse icon""" icon = download_result.pop(self.icon_url).fd.name shutil.copy(icon, join(self.install_path, self.icon_filename)) logger.debug("Copied icon: {}".format(self.icon_url)) class EclipseJava(BaseEclipse): """The Eclipse Java Edition distribution.""" download_keyword = 'eclipse-java-' executable = 'eclipse' def __init__(self, category): super().__init__(name="Eclipse", description=_("Eclipse Java IDE"), dir_to_decompress_in_tarball='eclipse', desktop_filename='eclipse-java.desktop', category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], icon_filename='java.png') class EclipseJEE(BaseEclipse): """The Eclipse JEE Edition distribution.""" download_keyword = 'eclipse-jee-' executable = 'eclipse' def __init__(self, category): super().__init__(name="Eclipse JEE", description=_("Eclipse JEE IDE"), dir_to_decompress_in_tarball='eclipse', desktop_filename='eclipse-jee.desktop', category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], icon_filename='javaee.png') class EclipsePHP(BaseEclipse): """The Eclipse PHP Edition distribution.""" download_keyword = 'eclipse-php-' executable = 'eclipse' def __init__(self, category): super().__init__(name="Eclipse PHP", description=_("Eclipse PHP IDE"), dir_to_decompress_in_tarball='eclipse', desktop_filename='eclipse-php.desktop', category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], icon_filename='php.png') class EclipseCPP(BaseEclipse): """The Eclipse CPP Edition distribution.""" download_keyword = 'eclipse-cpp-' executable = 'eclipse' def __init__(self, category): super().__init__(name="Eclipse CPP", description=_("Eclipse C/C++ IDE"), dir_to_decompress_in_tarball='eclipse', desktop_filename='eclipse-cpp.desktop', category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], icon_filename='cdt.png') class BaseJetBrains(umake.frameworks.baseinstaller.BaseInstaller, metaclass=ABCMeta): """The base for all JetBrains installers.""" def __init__(self, *args, **kwargs): """Add executable required file path to existing list""" if self.executable: current_required_files_path = kwargs.get("required_files_path", []) current_required_files_path.append(os.path.join("bin", self.executable)) kwargs["required_files_path"] = current_required_files_path download_page = "https://data.services.jetbrains.com/products/releases?code={}".format(self.download_keyword) kwargs["download_page"] = download_page super().__init__(*args, **kwargs) @property @abstractmethod def download_keyword(self): pass @property @abstractmethod def executable(self): pass @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): logger.debug("Fetched download page, parsing.") page = result[self.download_page] error_msg = page.error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) try: key, content = json.loads(page.buffer.read().decode()).popitem() download_url = content[0]['downloads']['linux']['link'] checksum_url = content[0]['downloads']['linux']['checksumLink'] except (IndexError): if '&type=eap' in self.download_page: logger.error("No EAP version available.") else: logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) except (json.JSONDecodeError): logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) logger.debug("Found download URL: " + download_url) logger.debug("Downloading checksum first, from " + checksum_url) def checksum_downloaded(results): checksum_result = next(iter(results.values())) # Just get the first. if checksum_result.error: logger.error(checksum_result.error) UI.return_main_screen(status_code=1) checksum = checksum_result.buffer.getvalue().decode('utf-8').split()[0] logger.info('Obtained SHA256 checksum: ' + checksum) self.download_requests.append(DownloadItem(download_url, checksum=Checksum(ChecksumType.sha256, checksum), ignore_encoding=True)) self.start_download_and_install() DownloadCenter([DownloadItem(checksum_url)], on_done=checksum_downloaded, download=False) def post_install(self): """Create the appropriate JetBrains launcher.""" icon_path = join(self.install_path, 'bin', self.icon_filename) comment = self.description + " (UDTC)" categories = "Development;IDE;" create_launcher(self.desktop_filename, get_application_desktop_file(name=self.name, icon_path=icon_path, exec='"{}" %f'.format(self.exec_path), comment=comment, categories=categories)) def install_framework_parser(self, parser): this_framework_parser = super().install_framework_parser(parser) this_framework_parser.add_argument('--eap', action="store_true", help=_("Install EAP version if available")) return this_framework_parser def run_for(self, args): if args.eap: self.download_page += '&type=eap' self.name += " EAP" self.description += " EAP" self.desktop_filename = self.desktop_filename.replace(".desktop", "-eap.desktop") self.install_path += "-eap" super().run_for(args) class PyCharm(BaseJetBrains): """The JetBrains PyCharm Community Edition distribution.""" download_keyword = 'PCC' executable = "pycharm.sh" def __init__(self, category): super().__init__(name="PyCharm", description=_("PyCharm Community Edition"), category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['python', 'python3'], dir_to_decompress_in_tarball='pycharm-community-*', desktop_filename='jetbrains-pycharm-ce.desktop', icon_filename='pycharm.png') class PyCharmEducational(BaseJetBrains): """The JetBrains PyCharm Educational Edition distribution.""" download_keyword = 'PCE' executable = "pycharm.sh" def __init__(self, category): super().__init__(name="PyCharm Educational", description=_("PyCharm Educational Edition"), category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['python', 'python3'], dir_to_decompress_in_tarball='pycharm-edu*', desktop_filename='jetbrains-pycharm-edu.desktop', icon_filename='pycharm.png') class PyCharmProfessional(BaseJetBrains): """The JetBrains PyCharm Professional Edition distribution.""" download_keyword = 'PCP' executable = "pycharm.sh" def __init__(self, category): super().__init__(name="PyCharm Professional", description=_("PyCharm Professional Edition"), category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['python', 'python3'], dir_to_decompress_in_tarball='pycharm-*', desktop_filename='jetbrains-pycharm.desktop', icon_filename='pycharm.png') class Idea(BaseJetBrains): """The JetBrains IntelliJ Idea Community Edition distribution.""" download_keyword = 'IIC' executable = "idea.sh" def __init__(self, category): super().__init__(name="Idea", description=_("IntelliJ IDEA Community Edition"), category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], dir_to_decompress_in_tarball='idea-IC-*', desktop_filename='jetbrains-idea-ce.desktop', icon_filename='idea.png') class IdeaUltimate(BaseJetBrains): """The JetBrains IntelliJ Idea Ultimate Edition distribution.""" download_keyword = 'IIU' executable = "idea.sh" def __init__(self, category): super().__init__(name="Idea Ultimate", description=_("IntelliJ IDEA"), category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], dir_to_decompress_in_tarball='idea-IU-*', desktop_filename='jetbrains-idea.desktop', icon_filename='idea.png') class RubyMine(BaseJetBrains): """The JetBrains RubyMine IDE""" download_keyword = 'RM' executable = "rubymine.sh" def __init__(self, category): super().__init__(name="RubyMine", description=_("Ruby on Rails IDE"), category=category, only_on_archs=['i386', 'amd64'], packages_requirements=['ruby'], dir_to_decompress_in_tarball='RubyMine-*', desktop_filename='jetbrains-rubymine.desktop', icon_filename='rubymine.png') class WebStorm(BaseJetBrains): """The JetBrains WebStorm IDE""" download_keyword = 'WS' executable = "webstorm.sh" def __init__(self, category): super().__init__(name="WebStorm", description=_("Complex client-side and server-side javascript IDE"), category=category, only_on_archs=['i386', 'amd64'], dir_to_decompress_in_tarball='WebStorm-*', desktop_filename='jetbrains-webstorm.desktop', icon_filename='webstorm.svg') class PhpStorm(BaseJetBrains): """The JetBrains PhpStorm IDE""" download_keyword = 'PS' executable = "phpstorm.sh" def __init__(self, category): super().__init__(name="PhpStorm", description=_("PHP and web development IDE"), category=category, only_on_archs=['i386', 'amd64'], dir_to_decompress_in_tarball='PhpStorm-*', desktop_filename='jetbrains-phpstorm.desktop', icon_filename='webide.png') class CLion(BaseJetBrains): """The JetBrains CLion IDE""" download_keyword = 'CL' executable = "clion.sh" def __init__(self, category): super().__init__(name="CLion", description=_("CLion integrated C/C++ IDE"), category=category, only_on_archs=['amd64'], dir_to_decompress_in_tarball='clion-*', desktop_filename='jetbrains-clion.desktop', icon_filename='clion.svg') class DataGrip(BaseJetBrains): """The JetBrains DataGrip IDE""" download_keyword = 'DG' executable = "datagrip.sh" def __init__(self, category): super().__init__(name="DataGrip", description=_("DataGrip SQL and databases IDE"), category=category, only_on_archs=['i386', 'amd64'], dir_to_decompress_in_tarball='DataGrip-*', desktop_filename='jetbrains-datagrip.desktop', icon_filename='product.png') class Arduino(umake.frameworks.baseinstaller.BaseInstaller): """The Arduino Software distribution.""" ARDUINO_GROUP = "dialout" def __init__(self, category): if os.geteuid() != 0: self._current_user = os.getenv("USER") self._current_user = pwd.getpwuid(int(os.getenv("SUDO_UID", default=0))).pw_name for group_name in [g.gr_name for g in grp.getgrall() if self._current_user in g.gr_mem]: if group_name == self.ARDUINO_GROUP: self.was_in_arduino_group = True break else: self.was_in_arduino_group = False super().__init__(name="Arduino", description=_("The Arduino Software Distribution"), category=category, only_on_archs=['i386', 'amd64'], download_page='http://www.arduino.cc/en/Main/Software', dir_to_decompress_in_tarball='arduino-*', desktop_filename='arduino.desktop', packages_requirements=['gcc-avr', 'avr-libc'], need_root_access=not self.was_in_arduino_group, required_files_path=["arduino"]) self.scraped_checksum_url = None self.scraped_download_url = None # This is needed later in several places. # The framework covers other cases, in combination with self.only_on_archs self.bits = '32' if platform.machine() == 'i686' else '64' @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): """We diverge from the BaseInstaller implementation a little here.""" logger.debug("Parse download metadata") error_msg = result[self.download_page].error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) soup = BeautifulSoup(result[self.download_page].buffer, 'html.parser') # We need to avoid matching arduino-nightly-... download_link_pat = r'arduino-[\d\.\-r]+-linux' + self.bits + '.tar.xz$' # Trap no match found, then, download/checksum url will be empty and will raise the error # instead of crashing. with suppress(TypeError): self.scraped_download_url = soup.find('a', href=re.compile(download_link_pat))['href'] self.scraped_checksum_url = soup.find('a', text=re.compile('Checksums'))['href'] self.scraped_download_url = 'http:' + self.scraped_download_url self.scraped_checksum_url = 'http:' + self.scraped_checksum_url if not self.scraped_download_url: logger.error("Can't parse the download link from %s.", self.download_page) UI.return_main_screen(status_code=1) if not self.scraped_checksum_url: logger.error("Can't parse the checksum link from %s.", self.download_page) UI.return_main_screen(status_code=1) DownloadCenter([DownloadItem(self.scraped_download_url), DownloadItem(self.scraped_checksum_url)], on_done=self.prepare_to_download_archive, download=False) @MainLoop.in_mainloop_thread def prepare_to_download_archive(self, results): """Store the md5 for later and fire off the actual download.""" download_page = results[self.scraped_download_url] checksum_page = results[self.scraped_checksum_url] if download_page.error: logger.error("Error fetching download page: %s", download_page.error) UI.return_main_screen(status_code=1) if checksum_page.error: logger.error("Error fetching checksums: %s", checksum_page.error) UI.return_main_screen(status_code=1) match = re.search(r'^(\S+)\s+arduino-[\d\.\-r]+-linux' + self.bits + '.tar.xz$', checksum_page.buffer.getvalue().decode('ascii'), re.M) if not match: logger.error("Can't find a checksum.") UI.return_main_screen(status_code=1) checksum = match.group(1) soup = BeautifulSoup(download_page.buffer.getvalue(), 'html.parser') btn = soup.find('button', text=re.compile('JUST DOWNLOAD')) if not btn: logger.error("Can't parse download button.") UI.return_main_screen(status_code=1) base_url = download_page.final_url cookies = download_page.cookies final_download_url = parse.urljoin(base_url, btn.parent['href']) logger.info('Final download url: %s, cookies: %s.', final_download_url, cookies) self.download_requests = [DownloadItem(final_download_url, checksum=Checksum(ChecksumType.md5, checksum), cookies=cookies)] # add the user to arduino group if not self.was_in_arduino_group: with futures.ProcessPoolExecutor(max_workers=1) as executor: f = executor.submit(_add_to_group, self._current_user, self.ARDUINO_GROUP) if not f.result(): UI.return_main_screen(status_code=1) self.start_download_and_install() def post_install(self): """Create the Arduino launcher""" icon_path = join(self.install_path, 'lib', 'arduino_icon.ico') comment = _("The Arduino Software IDE") categories = "Development;IDE;" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Arduino"), icon_path=icon_path, exec='"{}" %f'.format(self.exec_path), comment=comment, categories=categories)) if not self.was_in_arduino_group: UI.delayed_display(DisplayMessage(_("You need to logout and login again for your installation to work"))) class BaseNetBeans(umake.frameworks.baseinstaller.BaseInstaller): """The base for all Netbeans installers.""" BASE_URL = "http://download.netbeans.org/netbeans" EXECUTABLE = "nb/netbeans" def __init__(self, category, flavour=""): """The constructor. @param category The IDE category. @param flavour The Netbeans flavour (plugins bundled). """ # add a separator to the string, like -cpp if flavour: flavour = '-' + flavour self.flavour = flavour super().__init__(name="Netbeans", description=_("Netbeans IDE"), category=category, only_on_archs=['i386', 'amd64'], download_page="https://netbeans.org/downloads/zip.html", dir_to_decompress_in_tarball="netbeans*", desktop_filename="netbeans{}.desktop".format(flavour), packages_requirements=['openjdk-7-jdk | openjdk-8-jdk'], required_files_path=[os.path.join("bin", "netbeans")]) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): """Get the latest version and trigger the download of the download_page file. :param result: the file downloaded by DownloadCenter, contains a web page """ # Processing the string to obtain metadata (version) try: url_version_str = result[self.download_page].buffer.read().decode('utf-8') except AttributeError: # The file could not be parsed or there is no network connection logger.error("The download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) preg = re.compile(".*/images_www/v6/download/.*") for line in url_version_str.split("\n"): if preg.match(line): line = line.replace("var PAGE_ARTIFACTS_LOCATION = \"/images" "_www/v6/download/", "").replace("/\";", "").replace('/final', '') self.version = line.strip() if not self.version: # Fallback logger.error("Could not determine latest version") UI.return_main_screen(status_code=1) self.version_download_page = "https://netbeans.org/images_www/v6/download/" \ "{}/final/js/files.js".format(self.version) DownloadCenter([DownloadItem(self.version_download_page)], self.parse_download_page_callback, download=False) @MainLoop.in_mainloop_thread def parse_download_page_callback(self, result): """Get the download_url and trigger the download and installation of the app. :param result: the file downloaded by DownloadCenter, contains js functions with download urls """ logger.info("Netbeans {}".format(self.version)) # Processing the string to obtain metadata (download url) try: url_file = result[self.version_download_page].buffer.read().decode('utf-8') except AttributeError: # The file could not be parsed logger.error("The download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) preg = re.compile('add_file\("zip/netbeans-{}-[0-9]{{12}}{}.zip"'.format(self.version, self.flavour)) for line in url_file.split("\n"): if preg.match(line): # Clean up the string from js (it's a function call) line = line.replace("add_file(", "").replace(");", "").replace('"', "") url_string = line if not url_string: # The file could not be parsed logger.error("The download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) string_array = url_string.split(", ") try: url_suffix = string_array[0] sha256 = string_array[2] except IndexError: # The file could not be parsed logger.error("The download page changed its syntax or is not parsable") UI.return_main_screen(status_code=1) download_url = "{}/{}/final/{}".format(self.BASE_URL, self.version, url_suffix) self.download_requests.append(DownloadItem(download_url, Checksum(ChecksumType.sha256, sha256))) self.start_download_and_install() def post_install(self): """Create the Netbeans launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Netbeans IDE"), icon_path=join(self.install_path, "nb", "netbeans.png"), exec=self.exec_path, comment=_("Netbeans IDE"), categories="Development;IDE;")) class VisualStudioCode(umake.frameworks.baseinstaller.BaseInstaller): PERM_DOWNLOAD_LINKS = { "i686": "http://go.microsoft.com/fwlink/?LinkID=620885", "x86_64": "http://go.microsoft.com/fwlink/?LinkID=620884" } def __init__(self, category): super().__init__(name="Visual Studio Code", description=_("Visual Studio focused on modern web and cloud"), category=category, only_on_archs=['i386', 'amd64'], expect_license=True, download_page="https://code.visualstudio.com/License", desktop_filename="visual-studio-code.desktop", required_files_path=["bin/code"], dir_to_decompress_in_tarball="VSCode-linux-*", packages_requirements=["libgtk2.0-0"]) def parse_license(self, line, license_txt, in_license): """Parse Android Studio download page for license""" if 'SOFTWARE LICENSE TERMS' in line: in_license = True if in_license and "
" in line: in_license = False if in_license: license_txt.write(line.strip() + "\n") return in_license def parse_download_link(self, line, in_download): """We have persistent links for Visual Studio Code, return it right away""" url = None with suppress(KeyError): url = self.PERM_DOWNLOAD_LINKS[platform.machine()] return ((url, None), in_download) def post_install(self): """Create the Visual Studio Code launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Visual Studio Code"), icon_path=os.path.join(self.install_path, "resources", "app", "resources", "linux", "code.png"), exec=self.exec_path, comment=_("Visual Studio focused on modern web and cloud"), categories="Development;IDE;")) class LightTable(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="LightTable", description=_("LightTable code editor"), category=category, only_on_archs=['amd64'], download_page="https://api.github.com/repos/LightTable/LightTable/releases/latest", desktop_filename="lighttable.desktop", required_files_path=["LightTable"], dir_to_decompress_in_tarball="lighttable-*", checksum_type=ChecksumType.md5) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): logger.debug("Fetched download page, parsing.") page = result[self.download_page] error_msg = page.error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) try: assets = json.loads(page.buffer.read().decode())["assets"] download_url = None for asset in assets: if "linux" in asset["browser_download_url"]: download_url = asset["browser_download_url"] if not download_url: raise IndexError except (json.JSONDecodeError, IndexError): logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) logger.debug("Found download URL: " + download_url) self.download_requests.append(DownloadItem(download_url, None)) self.start_download_and_install() def post_install(self): """Create the LightTable Code launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("LightTable"), icon_path=os.path.join(self.install_path, "resources", "app", "core", "img", "lticon.png"), exec=self.exec_path, comment=_("LightTable code editor"), categories="Development;IDE;")) class Atom(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Atom", description=_("The hackable text editor"), category=category, only_on_archs=['amd64'], download_page="https://api.github.com/repos/Atom/Atom/releases/latest", desktop_filename="atom.desktop", required_files_path=["atom"], dir_to_decompress_in_tarball="atom-*", checksum_type=ChecksumType.md5) @MainLoop.in_mainloop_thread def get_metadata_and_check_license(self, result): logger.debug("Fetched download page, parsing.") page = result[self.download_page] error_msg = page.error if error_msg: logger.error("An error occurred while downloading {}: {}".format(self.download_page, error_msg)) UI.return_main_screen(status_code=1) try: assets = json.loads(page.buffer.read().decode())["assets"] download_url = None for asset in assets: if "tar.gz" in asset["browser_download_url"]: download_url = asset["browser_download_url"] if not download_url: raise IndexError except (json.JSONDecodeError, IndexError): logger.error("Can't parse the download URL from the download page.") UI.return_main_screen(status_code=1) logger.debug("Found download URL: " + download_url) self.download_requests.append(DownloadItem(download_url, None)) self.start_download_and_install() def post_install(self): """Create the Atom Code launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Atom"), icon_path=os.path.join(self.install_path, "atom.png"), exec=self.exec_path, comment=_("The hackable text editor"), categories="Development;IDE;")) class SublimeText(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Sublime Text", description=_("Sophisticated text editor for code, markup and prose"), category=category, only_on_archs=['i386', 'amd64'], download_page="https://sublimetext.com/3", desktop_filename="sublime-text.desktop", required_files_path=["sublime_text"], dir_to_decompress_in_tarball="sublime_text_*") arch_trans = { "amd64": "x64", "i386": "x32" } def parse_download_link(self, line, in_download): """Parse SublimeText download links""" url = None if '{}.tar.bz2'.format(self.arch_trans[get_current_arch()]) in line: p = re.search(r'also available as a [global_or_common_options] category [options from default framework]" as subparsers can't define default options and are not optional: http://bugs.python.org/issue9253 """ result_args = [] skip_all = False pending_args = [] category_name = None framework_completed = False args_to_append = [] for arg in args: # --remove is both installed as global and per-framework optional arguments. argparse will only analyze the # per framework one and will override the global one. So if --remove is before the category name, it will be # ignored. Mangle the arg and append it last then. if not category_name and arg in ("--remove", "-r"): args_to_append.append(arg) continue if not arg.startswith('-') and not skip_all: if not category_name: if arg in BaseCategory.categories.keys(): category_name = arg # file global and common options result_args.extend(pending_args) pending_args = [] result_args.append(arg) continue else: skip_all = True # will just append everything at the end elif not framework_completed: # if we found a real framework or not, consider that one. pending_args will be then filed framework_completed = True if arg in BaseCategory.categories[category_name].frameworks.keys(): result_args.append(arg) continue # take default framework if any after some sanitization check elif BaseCategory.categories[category_name].default_framework is not None: # before considering automatically inserting default framework, check that this argument has # some path separator into it. This is to avoid typos in framework selection and selecting default # framework with installation path where we didn't want to. if os.path.sep in arg: result_args.append(BaseCategory.categories[category_name].default_framework.prog_name) # current arg will be appending in pending_args else: skip_all = True # will just append everything at the end pending_args.append(arg) # this happened only if there is no argument after the category name if category_name and not framework_completed: if BaseCategory.categories[category_name].default_framework is not None: result_args.append(BaseCategory.categories[category_name].default_framework.prog_name) # let the rest in result_args.extend(pending_args) result_args.extend(args_to_append) return result_args def main(parser): """Main entry point of the cli command""" categories_parser = parser.add_subparsers(help='Developer environment', dest="category") for category in BaseCategory.categories.values(): category.install_category_parser(categories_parser) argcomplete.autocomplete(parser) # autocomplete will stop there. Can start more expensive operations now. arg_to_parse = sys.argv[1:] if "--help" not in arg_to_parse: # manipulate sys.argv for default frameworks: arg_to_parse = mangle_args_for_default_framework(arg_to_parse) args = parser.parse_args(arg_to_parse) if args.version: print(get_version()) sys.exit(0) if not args.category: parser.print_help() sys.exit(0) CliUI() run_command_for_args(args) ubuntu-make-16.11.1ubuntu1/umake/ui/cli/__pycache__/0000755000000000000000000000000013135606406017032 5ustar ubuntu-make-16.11.1ubuntu1/umake/ui/__pycache__/0000755000000000000000000000000013135606406016263 5ustar ubuntu-make-16.11.1ubuntu1/umake/version0000664000000000000000000000000713013560574015045 0ustar 16.11.1ubuntu-make-16.11.1ubuntu1/umake/network/0000775000000000000000000000000013135606406015131 5ustar ubuntu-make-16.11.1ubuntu1/umake/network/__init__.py0000664000000000000000000000000013013560574017230 0ustar ubuntu-make-16.11.1ubuntu1/umake/network/__pycache__/0000755000000000000000000000000013135606406017337 5ustar ubuntu-make-16.11.1ubuntu1/umake/network/requirements_handler.py0000664000000000000000000003362513013560574021734 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Module delivering a DownloadCenter to download in parallel multiple requests""" import apt import apt.progress import apt.progress.base from collections import namedtuple from concurrent import futures from contextlib import suppress import fcntl import logging import os import tempfile import time from umake.tools import Singleton, add_foreign_arch, get_foreign_archs, get_current_arch, as_root logger = logging.getLogger(__name__) class RequirementsHandler(object, metaclass=Singleton): """Handle platform requirements""" STATUS_DOWNLOADING, STATUS_INSTALLING = range(2) RequirementsResult = namedtuple("RequirementsResult", ["bucket", "error"]) def __init__(self): logger.info("Create a new apt cache") self.cache = apt.Cache() self.executor = futures.ThreadPoolExecutor(max_workers=1) def is_bucket_installed(self, bucket): """Check if the bucket is installed The bucket is a list of packages to check if installed.""" logger.debug("Check if {} is installed".format(bucket)) is_installed = True for pkg_name in bucket: if ' | ' in pkg_name: for package in pkg_name.split(' | '): if self.is_bucket_installed([package]): bucket.remove(pkg_name) bucket.append(package) pkg_name = package break # /!\ danger: if current arch == ':appended_arch', on a non multiarch system, dpkg doesn't # understand that. strip :arch then if ":" in pkg_name: (pkg_without_arch_name, arch) = pkg_name.split(":", -1) if arch == get_current_arch(): pkg_name = pkg_without_arch_name if pkg_name not in self.cache or not self.cache[pkg_name].is_installed: logger.info("{} isn't installed".format(pkg_name)) is_installed = False return is_installed def is_bucket_available(self, bucket): """Check if bucket available on the platform""" all_in_cache = True for pkg_name in bucket: if ' | ' in pkg_name: for package in pkg_name.split(' | '): if self.is_bucket_available([package]): bucket.remove(pkg_name) bucket.append(package) pkg_name = package break if pkg_name not in self.cache: # this can be also a foo:arch and we don't have added. Tell is may be available if ":" in pkg_name: # /!\ danger: if current arch == ':appended_arch', on a non multiarch system, dpkg doesn't # understand that. strip :arch then (pkg_without_arch_name, arch) = pkg_name.split(":", -1) if arch == get_current_arch() and pkg_without_arch_name in self.cache: # false positive, available continue elif arch not in get_foreign_archs(): # relax the constraint logger.info("{} isn't available on this platform, but {} isn't enabled. So it may be available " "later on".format(pkg_name, arch)) continue logger.info("{} isn't available on this platform".format(pkg_name)) all_in_cache = False return all_in_cache def is_bucket_uptodate(self, bucket): """Check if the bucket is installed and up to date The bucket is a list of packages to check if installed.""" logger.debug("Check if {} is uptodate".format(bucket)) is_installed_and_uptodate = True for pkg_name in bucket: # /!\ danger: if current arch == ':appended_arch', on a non multiarch system, dpkg doesn't # understand that. strip :arch then if ":" in pkg_name: (pkg_without_arch_name, arch) = pkg_name.split(":", -1) if arch == get_current_arch(): pkg_name = pkg_without_arch_name if pkg_name not in self.cache or not self.cache[pkg_name].is_installed: logger.info("{} isn't installed".format(pkg_name)) is_installed_and_uptodate = False elif self.cache[pkg_name].is_upgradable: logger.info("We can update {}".format(pkg_name)) is_installed_and_uptodate = False return is_installed_and_uptodate def install_bucket(self, bucket, progress_callback, installed_callback): """Install a specific bucket. If any other bucket is in progress, queue the request bucket is a list of packages to install. Return a tuple (num packages to install, size packages to download)""" logger.info("Installation {} pending".format(bucket)) bucket_pack = { "bucket": bucket, "progress_callback": progress_callback, "installed_callback": installed_callback } pkg_to_install = not self.is_bucket_uptodate(bucket) future = self.executor.submit(self._really_install_bucket, bucket_pack) future.tag_bucket = bucket_pack future.add_done_callback(self._on_done) return pkg_to_install def _really_install_bucket(self, current_bucket): """Really install current bucket and bind signals""" bucket = current_bucket["bucket"] logger.debug("Starting {} installation".format(bucket)) # exchange file output for apt and dpkg after the fork() call (open it empty) self.apt_fd = tempfile.NamedTemporaryFile(delete=False) self.apt_fd.close() if self.is_bucket_uptodate(bucket): return True need_cache_reload = False for pkg_name in bucket: if ":" in pkg_name: arch = pkg_name.split(":", -1)[-1] need_cache_reload = need_cache_reload or add_foreign_arch(arch) if need_cache_reload: with as_root(): self._force_reload_apt_cache() self.cache.update() self._force_reload_apt_cache() # mark for install and so on for pkg_name in bucket: # /!\ danger: if current arch == ':appended_arch', on a non multiarch system, dpkg doesn't understand that # strip :arch then if ":" in pkg_name: (pkg_without_arch_name, arch) = pkg_name.split(":", -1) if arch == get_current_arch(): pkg_name = pkg_without_arch_name try: pkg = self.cache[pkg_name] if pkg.is_installed and pkg.is_upgradable: logger.debug("Marking {} for upgrade".format(pkg_name)) pkg.mark_upgrade() else: logger.debug("Marking {} for install".format(pkg_name)) pkg.mark_install(auto_fix=False) except Exception as msg: message = "Can't mark for install {}: {}".format(pkg_name, msg) raise BaseException(message) # this can raise on installedArchives() exception if the commit() fails with as_root(): self.cache.commit(fetch_progress=self._FetchProgress(current_bucket, self.STATUS_DOWNLOADING, current_bucket["progress_callback"]), install_progress=self._InstallProgress(current_bucket, self.STATUS_INSTALLING, current_bucket["progress_callback"], self._force_reload_apt_cache, self.apt_fd.name)) return True def _on_done(self, future): """Call future associated bucket done callback""" result = self.RequirementsResult(bucket=future.tag_bucket["bucket"], error=None) if future.exception(): error_message = str(future.exception()) with suppress(FileNotFoundError): with open(self.apt_fd.name) as f: subprocess_content = f.read() if subprocess_content: error_message = "{}\nSubprocess output: {}".format(error_message, subprocess_content) logger.error(error_message) result = result._replace(error=error_message) else: logger.debug("{} installed".format(future.tag_bucket["bucket"])) os.remove(self.apt_fd.name) future.tag_bucket["installed_callback"](result) def _force_reload_apt_cache(self): """Loop on loading apt cache in case something else is updating""" try: self.cache.open() except SystemError: time.sleep(1) self._force_reload_apt_cache() class _FetchProgress(apt.progress.base.AcquireProgress): """Progress handler for downloading a bucket""" def __init__(self, bucket, status, progress_callback,): apt.progress.base.AcquireProgress.__init__(self) self._bucket = bucket self._status = status self._progress_callback = progress_callback def pulse(self, owner): percent = (((self.current_bytes + self.current_items) * 100.0) / float(self.total_bytes + self.total_items)) logger.debug("{} download update: {}% of {}".format(self._bucket['bucket'], percent, self.total_bytes)) report = {"step": self._status, "percentage": percent, "pkg_size_download": self.total_bytes} self._progress_callback(report) class _InstallProgress(apt.progress.base.InstallProgress): """Progress handler for installing a bucket""" def __init__(self, bucket, status, progress_callback, force_load_apt_cache, exchange_filename): apt.progress.base.InstallProgress.__init__(self) self._bucket = bucket self._status = status self._progress_callback = progress_callback self._force_reload_apt_cache = force_load_apt_cache self._exchange_filename = exchange_filename def error(self, pkg, msg): logger.error("{} installation finished with an error: {}".format(self._bucket['bucket'], msg)) self._force_reload_apt_cache() # reload apt cache raise BaseException(msg) def finish_update(self): # warning: this function can be called even if dpkg failed (it raised an exception around commit() # DO NOT CALL directly the callbacks from there. logger.debug("Install for {} ended.".format(self._bucket['bucket'])) self._force_reload_apt_cache() # reload apt cache def status_change(self, pkg, percent, status): logger.debug("{} install update: {}".format(self._bucket['bucket'], percent)) self._progress_callback({"step": self._status, "percentage": percent}) @staticmethod def _redirect_stdin(): # pragma: no cover (in a fork) os.dup2(os.open(os.devnull, os.O_RDWR), 0) def _redirect_output(self): # pragma: no cover (in a fork) fd = os.open(self._exchange_filename, os.O_RDWR) os.dup2(fd, 1) os.dup2(fd, 2) def _fixup_fds(self): # pragma: no cover (in a fork) required_fds = [0, 1, 2, # stdin, stdout, stderr self.writefd, self.write_stream.fileno(), self.statusfd, self.status_stream.fileno() ] # ensure that our required fds close on exec for fd in required_fds[3:]: old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC) # close all fds proc_fd = "/proc/self/fd" if os.path.exists(proc_fd): error_count = 0 for fdname in os.listdir(proc_fd): try: fd = int(fdname) except ValueError: print("ERROR: can not get fd for '%s'" % fdname) if fd in required_fds: continue try: os.close(fd) except OSError as e: # there will be one fd that can not be closed # as its the fd from pythons internal diropen() # so its ok to ignore one close error error_count += 1 if error_count > 1: print("ERROR: os.close(%s): %s" % (fd, e)) def fork(self): pid = os.fork() if pid == 0: # pragma: no cover # be root os.seteuid(0) os.setegid(0) self._fixup_fds() self._redirect_stdin() self._redirect_output() return pid ubuntu-make-16.11.1ubuntu1/umake/network/download_center.py0000664000000000000000000002326513013560574020662 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Module delivering a DownloadCenter to download in parallel multiple requests""" from collections import namedtuple from concurrent import futures from contextlib import closing import hashlib from io import BytesIO import logging import os import tempfile import requests import requests.exceptions from umake.network.ftp_adapter import FTPAdapter from umake.tools import ChecksumType, root_lock logger = logging.getLogger(__name__) class DownloadItem(namedtuple('DownloadItem', ['url', 'checksum', 'headers', 'ignore_encoding', 'cookies'])): """An individual item to be downloaded and checked. Checksum should be an instance of tools.Checksum, if provided. Headers should be a dictionary of HTTP headers, if provided. Cookies should be a cookie dictionary, if provided.""" def __new__(cls, url, checksum=None, headers=None, ignore_encoding=False, cookies=None): return super().__new__(cls, url, checksum, headers, ignore_encoding, cookies) class DownloadCenter: """Read or download requested urls in separate threads.""" BLOCK_SIZE = 1024 * 8 # from urlretrieve code DownloadResult = namedtuple("DownloadResult", ["buffer", "error", "fd", "final_url", "cookies"]) def __init__(self, urls, on_done, download=True, report=lambda x: None): """Generate a threaded download machine. urls is a list of DownloadItems to download or read from. on_done is the callback that will be called once all those urls are downloaded. report, if not None, will be called once any download is in progress, reporting a dict of current download with current/size parameters The callback will get a dictionary parameter like: { "url": DownloadResult(buffer=page content as bytes if download is set to False. close() will clean it from memory, error=string detailing the error which occurred (path and content would be empty), fd=temporary file descriptor. close() will delete it from disk, final_url=the final url, which may be different from the start if there were redirects, cookies=a dictionary of cookies after the request ) } """ self._done_callback = on_done self._wired_report = report self._download_to_file = download self._urls = urls self._downloaded_content = {} self._download_progress = {} executor = futures.ThreadPoolExecutor(max_workers=len(urls)) for url_request in self._urls: # grab the md5sum if any # switch between inline memory and temp file if download: # Named because shutils and tarfile library needs a .name property # http://bugs.python.org/issue21044 # also, ensure we keep the same suffix path, ext = os.path.splitext(url_request.url) # We want to ensure that we don't create files as root root_lock.acquire() dest = tempfile.NamedTemporaryFile(suffix=ext) root_lock.release() logger.info("Start downloading {} to a temp file".format(url_request)) else: dest = BytesIO() logger.info("Start downloading {} in memory".format(url_request)) future = executor.submit(self._fetch, url_request, dest) future.tag_url = url_request.url future.tag_download = download future.tag_dest = dest future.add_done_callback(self._one_done) def _fetch(self, download_item, dest): """Get an url content and close the connexion. This will write the content to dest and check for md5sum. Return a tuple of (dest, final_url, cookies) """ url = download_item.url checksum = download_item.checksum headers = download_item.headers or {} cookies = download_item.cookies def _report(block_no, block_size, total_size): current_size = int(block_no * block_size) if total_size != -1: current_size = min(current_size, total_size) self._download_progress[url] = {"current": current_size, "size": total_size} logger.debug("Deliver download update: {} of {}".format(self._download_progress, total_size)) self._wired_report(self._download_progress) # Requests support redirection out of the box. # Create a session so we can mount our own FTP adapter. session = requests.Session() session.mount('ftp://', FTPAdapter()) try: with closing(session.get(url, stream=True, headers=headers, cookies=cookies)) as r: r.raise_for_status() content_size = int(r.headers.get('content-length', -1)) # read in chunk and send report updates block_num = 0 _report(block_num, self.BLOCK_SIZE, content_size) for data in r.raw.stream(amt=self.BLOCK_SIZE, decode_content=not download_item.ignore_encoding): dest.write(data) block_num += 1 _report(block_num, self.BLOCK_SIZE, content_size) final_url = r.url cookies = session.cookies except requests.exceptions.InvalidSchema as exc: # Wrap this for a nicer error message. raise BaseException("Protocol not supported.") from exc if checksum and checksum.checksum_value: checksum_type = checksum.checksum_type checksum_value = checksum.checksum_value logger.debug("Checking checksum ({}).".format(checksum_type.name)) dest.seek(0) if checksum_type is ChecksumType.sha1: actual_checksum = self.sha1_for_fd(dest) elif checksum_type is ChecksumType.md5: actual_checksum = self.md5_for_fd(dest) elif checksum_type is ChecksumType.sha256: actual_checksum = self.sha256_for_fd(dest) elif checksum_type is ChecksumType.sha512: actual_checksum = self.sha512_for_fd(dest) else: msg = "Unsupported checksum type: {}.".format(checksum_type) raise BaseException(msg) logger.debug("Expected: {}, actual: {}.".format(checksum_value, actual_checksum)) if checksum_value != actual_checksum: msg = ("The checksum of {} doesn't match. Corrupted download? " "Aborting.").format(url) raise BaseException(msg) return dest, final_url, cookies def _one_done(self, future): """Callback that will be called once the download finishes. (will be wired on the constructor) """ if future.exception(): logger.error("{} couldn't finish download: {}".format(future.tag_url, future.exception())) result = self.DownloadResult(buffer=None, error=str(future.exception()), fd=None, final_url=None, cookies=None) # cleaned unusable temp file as something bad happened future.tag_dest.close() else: logger.info("{} download finished".format(future.tag_url)) fd, final_url, cookies = future.result() fd.seek(0) if future.tag_download: result = self.DownloadResult(buffer=None, error=None, fd=fd, final_url=final_url, cookies=cookies) else: result = self.DownloadResult(buffer=fd, error=None, fd=None, final_url=final_url, cookies=cookies) self._downloaded_content[future.tag_url] = result if len(self._urls) == len(self._downloaded_content): self._done() def _done(self): """Callback that will be called once all download finishes. uris of the temporary files will be passed on the wired callback """ logger.info("All pending downloads for {} done".format(self._urls)) self._done_callback(self._downloaded_content) @classmethod def _checksum_for_fd(cls, algorithm, f, block_size=2 ** 20): checksum = algorithm() while True: data = f.read(block_size) if not data: break checksum.update(data) return checksum.hexdigest() @classmethod def md5_for_fd(cls, f, block_size=2 ** 20): return cls._checksum_for_fd(hashlib.md5, f, block_size) @classmethod def sha1_for_fd(cls, f, block_size=2 ** 20): return cls._checksum_for_fd(hashlib.sha1, f, block_size) @classmethod def sha256_for_fd(cls, f, block_size=2 ** 20): return cls._checksum_for_fd(hashlib.sha256, f, block_size) @classmethod def sha512_for_fd(cls, f, block_size=2 ** 20): return cls._checksum_for_fd(hashlib.sha512, f, block_size) ubuntu-make-16.11.1ubuntu1/umake/network/ftp_adapter.py0000664000000000000000000000742113013560574020000 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Tin Tvrtković # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from collections import namedtuple from ftplib import FTP, error_perm from queue import Queue from threading import Thread import urllib.parse from requests import Response from requests.adapters import BaseAdapter import requests.exceptions class FTPAdapter(BaseAdapter): """An FTP adapter for requests. Supports streaming GETs and not much else.""" @staticmethod def get_connection(hostname, timeout=None): return FTP(host=hostname, timeout=timeout, user='anonymous') def send(self, request, stream=False, timeout=None, **kwargs): parsed_url = urllib.parse.urlparse(request.url) file_path = parsed_url.path # Strip the leading slash, if present. if file_path.startswith('/'): file_path = file_path[1:] try: self.conn = self.get_connection(parsed_url.netloc, timeout) except ConnectionRefusedError as exc: # Wrap this in a requests exception. # in requests 2.2.1, ConnectionError does not take keyword args raise requests.exceptions.ConnectionError() from exc resp = Response() resp.url = request.url try: size = self.conn.size(file_path) except error_perm: resp.status_code = 404 return resp if stream: # We have to do this in a background thread, since ftplib's and requests' approaches are the opposite: # ftplib is callback based, and requests needs to expose an iterable. (Push vs pull) # When the queue size is reached, puts will block. This provides some backpressure. queue = Queue(maxsize=100) done_sentinel = object() def handle_transfer(): # Download all the chunks into a queue, then place a sentinel object into it to signal completion. self.conn.retrbinary('RETR ' + file_path, queue.put) queue.put(done_sentinel) Thread(target=handle_transfer).start() def stream(amt=8192, decode_content=False): """A generator, yielding chunks from the queue.""" # We maintain a buffer so the consumer gets exactly the number of bytes requested. buffer = bytearray() while True: data = queue.get() if data is not done_sentinel: buffer.extend(data) if len(buffer) >= amt: result = buffer[:amt] buffer = buffer[amt:] yield result else: if buffer: yield buffer return Raw = namedtuple('raw', 'stream') raw = Raw(stream) resp.status_code = 200 resp.raw = raw resp.headers['content-length'] = size resp.close = lambda: self.conn.close() return resp else: # Not relevant for Ubuntu Make. raise NotImplementedError ubuntu-make-16.11.1ubuntu1/umake/__pycache__/0000755000000000000000000000000013135606406015646 5ustar ubuntu-make-16.11.1ubuntu1/umake/interactions/0000775000000000000000000000000013135606406016142 5ustar ubuntu-make-16.11.1ubuntu1/umake/interactions/__init__.py0000664000000000000000000001446513013560574020265 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # module gather different types of interactions with the UI from gettext import gettext as _ import logging from umake.tools import InputError logger = logging.getLogger(__name__) class Choice: def __init__(self, id, label, callback_fn, txt_shorcut=None, is_default=False): """Choice element containing label and callback function""" self.id = id self.label = label self.txt_shorcut = txt_shorcut self.callback_fn = callback_fn self.is_default = is_default class TextWithChoices: def __init__(self, content, choices=[], newline_before_option=False): """Content text with a list of multiple Choice elements""" current_ids = [] default_found = False for choice in choices: if choice.id in current_ids: message = "{} choice id is already in registered ids. Can't instantiate this " \ "interaction".format(choice.id) logger.error(message) raise BaseException(message) current_ids.append(choice.id) if choice.is_default: if default_found: message = "One default was already registered, can't register a second one in that choices set: {}"\ .format([choice.label for choice in choices]) logger.error(message) raise BaseException(message) default_found = True self.content = content self.choices = choices self.newline_before_option = newline_before_option def choose(self, choice_id=None, answer=None): """Return associated callback for choice""" for choice in self.choices: if (choice_id is not None and choice.id == choice_id) or\ (answer is not None and (choice.label.lower() == answer.lower() or (choice.txt_shorcut is not None and choice.txt_shorcut.lower() == answer.lower()))): return choice.callback_fn() msg = _("No suitable answer provided") if choice_id is not None: msg = _("Your entry '{}' isn't an acceptable choice. choices are: {}")\ .format(choice_id, [choice.id for choice in self.choices]) if answer is not None: txt_shortcuts = [choice.txt_shorcut for choice in self.choices if choice.txt_shorcut is not None] if txt_shortcuts: msg = _("Your entry '{}' isn't an acceptable choice. choices are: {} and {}")\ .format(answer, txt_shortcuts, [choice.label for choice in self.choices]) else: msg = _("Your entry '{}' isn't an acceptable choice. choices are: {}")\ .format(answer, [choice.label for choice in self.choices]) if not choice_id and not answer: for choice in self.choices: if choice.is_default: return choice.callback_fn() raise InputError(msg) @property def prompt(self): """Text prompt handling if we do have some shortcuts""" possible_answers = [] for choice in self.choices: answer = choice.label if choice.txt_shorcut: # NOTE: sum of answers answer += _(" ({})").format((choice.txt_shorcut)) possible_answers.append(answer) if self.newline_before_option: # NOTE: first is prompt, newline and then set of answers prompt = _("{}\n[{}] ").format(self.content, '/'.join(possible_answers)) else: # NOTE: first is prompt, then set of answers: prompt = _("{} [{}] ").format(self.content, '/'.join(possible_answers)) return prompt class LicenseAgreement(TextWithChoices): def __init__(self, content, callback_yes, callback_no): """License agreement text with accept/decline""" choices = [Choice(0, _("I Accept"), callback_yes, txt_shorcut=_("a")), Choice(1, _("I don't accept"), callback_no, txt_shorcut=_("N"), is_default=True)] super().__init__(content, choices=choices, newline_before_option=True) @property def input(self): """Text input prompt handling if we do have some shortcuts""" answers = [] for choice in self.choices: # NOTE: first element is choice, and then shortcut _("{} ({})") answer = _("{} ({})").format(choice.label, choice.txt_shorcut) answers.append(answer) # append different possible choices return _("[{}] ").format('/'.join(answers)) class InputText: def __init__(self, content, callback_fn, default_input=""): """Content text with an line input""" self.content = content self._callback_fn = callback_fn self.default_input = default_input def run_callback(self, result): self._callback_fn(result) class YesNo(TextWithChoices): def __init__(self, content, callback_yes, callback_no, default_is_yes=False): """Return a basic Yes No question, default being false or overriden""" super().__init__(content, [Choice(0, _("Yes"), callback_yes, txt_shorcut=_('y'), is_default=default_is_yes), Choice(1, _("No"), callback_no, txt_shorcut=_("N"), is_default=(not default_is_yes))]) class DisplayMessage: def __init__(self, text): self.text = text class UnknownProgress: def __init__(self, iterator): self.bar = None self._iterator = iterator ubuntu-make-16.11.1ubuntu1/umake/interactions/__pycache__/0000755000000000000000000000000013135606406020350 5ustar ubuntu-make-16.11.1ubuntu1/umake/tools.py0000664000000000000000000003713313013560574015161 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from collections import namedtuple from contextlib import contextmanager, suppress from enum import unique, Enum from gettext import gettext as _ from gi.repository import GLib, Gio from glob import glob import logging import os import re import shutil import signal import subprocess import sys from textwrap import dedent from time import sleep from threading import Lock from umake import settings from xdg.BaseDirectory import load_first_config, xdg_config_home, xdg_data_home import yaml import yaml.scanner import yaml.parser logger = logging.getLogger(__name__) # cache current arch. Shouldn't change in the life of the process ;) _current_arch = None _foreign_arch = None _version = None profile_tag = _("# Ubuntu make installation of {}\n") root_lock = Lock() @unique class ChecksumType(Enum): """Types of supported checksum algorithms.""" md5 = "md5" sha1 = "sha1" sha256 = "sha256" sha512 = "sha512" class Checksum(namedtuple('Checksum', ['checksum_type', 'checksum_value'])): """A combination of checksum algorithm and actual value to check.""" pass class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class ConfigHandler(metaclass=Singleton): def __init__(self): """Load the config""" self._config = {} old_config_file = load_first_config(settings.OLD_CONFIG_FILENAME) config_file = load_first_config(settings.CONFIG_FILENAME) if old_config_file: if not config_file: config_file = old_config_file.replace(settings.OLD_CONFIG_FILENAME, settings.CONFIG_FILENAME) os.rename(old_config_file, config_file) logger.debug("Opening {}".format(config_file)) try: with open(config_file) as f: self._config = yaml.load(f) except (TypeError, FileNotFoundError): logger.info("No configuration file found") except (yaml.scanner.ScannerError, yaml.parser.ParserError) as e: logger.error("Invalid configuration file found: {}".format(e)) @property def config(self): return self._config @config.setter def config(self, config): config_file = os.path.join(xdg_config_home, settings.CONFIG_FILENAME) logging.debug("Saving new configuration: {} in {}".format(config, config_file)) os.makedirs(os.path.dirname(config_file), exist_ok=True) with open(config_file, 'w') as f: yaml.dump(config, f, default_flow_style=False) self._config = config class NoneDict(dict): """We don't use a defaultdict(lambda: None) as it's growing everytime something is requested""" def __getitem__(self, key): return dict.get(self, key) class classproperty(object): """Class property, similar to instance properties""" def __init__(self, f): self.f = f def __get__(self, obj, owner): return self.f(owner) class MainLoop(object, metaclass=Singleton): """Mainloop simple wrapper""" def __init__(self): self.mainloop = GLib.MainLoop() # Glib steals the SIGINT handler and so, causes issue in the callback # https://bugzilla.gnome.org/show_bug.cgi?id=622084 signal.signal(signal.SIGINT, signal.SIG_DFL) def run(self): self.mainloop.run() def quit(self, status_code=0, raise_exception=True): GLib.timeout_add(80, self._clean_up, status_code) # only raises exception if not turned down (like in tests, where we are not in the mainloop for sure) if raise_exception: raise self.ReturnMainLoop() def _clean_up(self, exit_code): self.mainloop.quit() sys.exit(exit_code) @staticmethod def in_mainloop_thread(function): """Decorator to run a function in a mainloop thread""" # GLib.idle_add doesn't propagate try: except in the mainloop, so we handle it there for all functions def wrapper(*args, **kwargs): try: function(*args, **kwargs) except MainLoop.ReturnMainLoop: pass except BaseException: logger.exception("Unhandled exception") GLib.idle_add(MainLoop().quit, 1, False) def inner(*args, **kwargs): return GLib.idle_add(wrapper, *args, **kwargs) return inner class ReturnMainLoop(BaseException): """Exception raised only to return to MainLoop without finishing the function""" class InputError(BaseException): """Exception raised for errors in the input. Attributes: expr -- input expression in which the error occurred msg -- explanation of the error """ def __init__(self, value): self.value = value def __str__(self): return repr(self.value) def get_current_arch(): """Get current configuration dpkg architecture. Possible outputs: * amd64 * i386 """ global _current_arch if _current_arch is None: _current_arch = subprocess.check_output(["dpkg", "--print-architecture"], universal_newlines=True).rstrip("\n") return _current_arch def get_foreign_archs(): """Get foreign architectures that were enabled""" global _foreign_arch if _foreign_arch is None: _foreign_arch = subprocess.check_output(["dpkg", "--print-foreign-architectures"], universal_newlines=True)\ .rstrip("\n").split() return _foreign_arch def add_foreign_arch(new_arch): """Add a new architecture if not already loaded. Return if new arch was added""" global _foreign_arch # try to add the arch if not already present arch_added = False if new_arch not in get_foreign_archs() and new_arch != get_current_arch(): logger.info("Adding foreign arch: {}".format(new_arch)) with open(os.devnull, "w") as f: with as_root(): if subprocess.call(["dpkg", "--add-architecture", new_arch], stdout=f) != 0: msg = _("Can't add foreign architecture {}").format(new_arch) raise BaseException(msg) # mark the new arch as added and invalidate the cache arch_added = True _foreign_arch = None return arch_added def get_current_ubuntu_version(): """Return current ubuntu version or raise an error if couldn't find any""" global _version if _version is None: try: with open(settings.LSB_RELEASE_FILE) as lsb_release_file: for line in lsb_release_file: line = line.strip() if line.startswith('DISTRIB_RELEASE='): tag, release = line.split('=', 1) _version = release break else: message = "Couldn't find DISTRIB_RELEASE in {}".format(settings.LSB_RELEASE_FILE) logger.error(message) raise BaseException(message) except (FileNotFoundError, IOError) as e: message = "Can't open lsb-release file: {}".format(e) logger.error(message) raise BaseException(message) return _version def is_completion_mode(): """Return true if we are in completion mode""" return os.environ.get('_ARGCOMPLETE') == '1' def get_user_frameworks_path(): """Return user frameworks local path""" return os.path.expanduser(os.path.join('~', '.umake', 'frameworks')) def get_icon_path(icon_filename): """Return local icon path""" return os.path.join(xdg_data_home, "icons", icon_filename) def get_launcher_path(desktop_filename): """Return launcher path""" return os.path.join(xdg_data_home, "applications", desktop_filename) def launcher_exists(desktop_filename): """Return true if the desktop filename exists""" exists = os.path.exists(get_launcher_path(desktop_filename)) if not exists: logger.debug("{} doesn't exist".format(desktop_filename)) return False return True def launcher_exists_and_is_pinned(desktop_filename): """Return true if the desktop filename is pinned in the launcher""" if not launcher_exists(desktop_filename): return False if os.environ.get("XDG_CURRENT_DESKTOP") != "Unity": logger.debug("Don't check launcher as current environment isn't Unity") return True if "com.canonical.Unity.Launcher" not in Gio.Settings.list_schemas(): logger.debug("In an Unity environment without the Launcher schema file") return False gsettings = Gio.Settings(schema_id="com.canonical.Unity.Launcher", path="/com/canonical/unity/launcher/") launcher_list = gsettings.get_strv("favorites") res = "application://" + desktop_filename in launcher_list if not res: logger.debug("Launcher exists but is not pinned (pinned: {}).".format(launcher_list)) return res def copy_icon(source_icon_filepath, icon_filename): """copy icon from source filepath to xdg destination as icon_filename globs are accepted in the filepath""" icon_path = get_icon_path(icon_filename) os.makedirs(os.path.dirname(icon_path), exist_ok=True) for file_path in glob(source_icon_filepath): logger.debug("Copy icon from {} to {}".format(file_path, icon_path)) shutil.copy(file_path, icon_path) break else: logger.warning("Didn't find any icon for the launcher.") def create_launcher(desktop_filename, content): """Create a desktop file and an unity launcher icon""" # Create file in standard location launcher_path = get_launcher_path(desktop_filename) os.makedirs(os.path.dirname(launcher_path), exist_ok=True) logger.debug("Create launcher as {}".format(launcher_path)) with open(launcher_path, "w") as f: f.write(content) if "com.canonical.Unity.Launcher" not in Gio.Settings.list_schemas(): logger.info("Don't create a launcher icon, as we are not under Unity") return gsettings = Gio.Settings(schema_id="com.canonical.Unity.Launcher", path="/com/canonical/unity/launcher/") launcher_list = gsettings.get_strv("favorites") launcher_tag = "application://{}".format(desktop_filename) if launcher_tag not in launcher_list: index = len(launcher_list) with suppress(ValueError): index = launcher_list.index("unity://running-apps") launcher_list.insert(index, launcher_tag) # FIXME: working around a bug in glib: https://bugzilla.gnome.org/show_bug.cgi?id=744030 sleep(1.5) ########## gsettings.set_strv("favorites", launcher_list) def add_exec_link(exec_path, destination_name): bin_folder = settings.DEFAULT_BINARY_LINK_PATH os.makedirs(bin_folder, exist_ok=True) add_env_to_user("Ubuntu Make binary symlink", {"PATH": {"value": bin_folder}}) full_dest_path = os.path.join(bin_folder, destination_name) with suppress(FileNotFoundError): os.remove(full_dest_path) os.symlink(exec_path, full_dest_path) def get_application_desktop_file(name="", icon_path="", exec="", comment="", categories="", extra=""): """Get a desktop file string content""" return dedent("""\ [Desktop Entry] Version=1.0 Type=Application Name={name} Icon={icon_path} Exec={exec} Comment={comment} Categories={categories} Terminal=false {extra} """).format(name=name, icon_path=icon_path, exec=exec, comment=comment, categories=categories, extra=extra) def strip_tags(content): """Strip all HTML tags from content""" return re.sub('<[^<]+?>', '', content) def switch_to_current_user(): """Switch euid and guid to current user if current user is root""" if os.geteuid() != 0: return # fallback to root user if no SUDO_GID (should be su - root) os.setegid(int(os.getenv("SUDO_GID", default=0))) os.seteuid(int(os.getenv("SUDO_UID", default=0))) @contextmanager def as_root(): # block all other threads making sensitive operations root_lock.acquire() try: os.seteuid(0) os.setegid(0) yield finally: switch_to_current_user() root_lock.release() # TODO: make that useful for more shells def _get_shell_profile_file_path(): """Return profile filepath for current preferred shell""" current_shell = os.getenv('SHELL', '/bin/bash').lower() profile_filename = '.zprofile' if 'zsh' in current_shell else '.profile' return os.path.join(os.path.expanduser('~'), profile_filename) def remove_framework_envs_from_user(framework_tag): """Remove all envs from user if found""" profile_filepath = _get_shell_profile_file_path() content = "" framework_header = profile_tag.format(framework_tag) try: with open(profile_filepath, "r", encoding='utf-8') as f: content = f.read() except FileNotFoundError: return if framework_header not in content: return while framework_header in content: framework_start_index = content.find(framework_header) framework_end_index = content[framework_start_index:].find("\n\n") content = content[:framework_start_index] + content[framework_start_index + framework_end_index + len("\n\n"):] # rewrite .profile and omit framework_tag with open(profile_filepath + ".new", "w", encoding='utf-8') as f: f.write(content) os.rename(profile_filepath + ".new", profile_filepath) def add_env_to_user(framework_tag, env_dict): """Add args to user env in .profile (.zprofile if zsh) if the user doesn't have that env with those args env_dict is a dictionary of: { env_variable: { value: value, keep: True/False } } value is either a list (in that case, it's concatenated) or a string If keep is set to True, we keep previous values with :$OLDERENV.""" profile_filepath = _get_shell_profile_file_path() remove_framework_envs_from_user(framework_tag) envs_to_insert = {} for env in env_dict: value = env_dict[env]["value"] if isinstance(value, list): value = os.pathsep.join(value) if env_dict[env].get("keep", True) and os.environ.get(env): os.environ[env] = value + os.pathsep + os.environ[env] value = "{}{}${}".format(value, os.pathsep, env) else: os.environ[env] = value envs_to_insert[env] = value with open(profile_filepath, "a", encoding='utf-8') as f: f.write(profile_tag.format(framework_tag)) for env in envs_to_insert: value = envs_to_insert[env] logger.debug("Adding {} to user's {} for {}".format(value, env, framework_tag)) export = "" if env != "PATH": export = "export " f.write("{}{}={}\n".format(export, env, value)) f.write("\n") ubuntu-make-16.11.1ubuntu1/umake/decompressor.py0000664000000000000000000001433213135605140016514 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from collections import namedtuple from concurrent import futures from glob import glob import logging import os import shutil import stat import subprocess import tarfile import tempfile import zipfile logger = logging.getLogger(__name__) class Decompressor: """Handle decompression of various file in separate threads""" DecompressOrder = namedtuple("DecompressOrder", ["dir", "dest"]) DecompressResult = namedtuple("DecompressResult", ["error"]) # override _extract_member to preserve file permissions: # http://bugs.python.org/issue15795 class ZipFileWithPerm(zipfile.ZipFile): def _extract_member(self, member, targetpath, pwd): if not isinstance(member, zipfile.ZipInfo): member = self.getinfo(member) targetpath = super()._extract_member(member, targetpath, pwd) mode = member.external_attr >> 16 & 0x1FF os.chmod(targetpath, mode) return targetpath def __init__(self, orders, on_done): """Decompress all fds in threads and send on_done callback once finished order is: { "fd": DecompressOrder(dir=directory to decompress (this will become the new root) dest=destination directory to use for decompressing) ) } Return a dict of DecompressResult on the on_done callback: { "fd": DecompressResult(error=optional error if anything went wrong" } """ self._orders = orders self._decompressed = {} self._done_callback = on_done executor = futures.ThreadPoolExecutor(max_workers=3) for fd in orders: logger.info("Requesting decompression to {}".format(orders[fd].dest)) future = executor.submit(self._decompress, fd, orders[fd].dir, orders[fd].dest) future.tag_fd = fd future.tag_dest = orders[fd].dest future.add_done_callback(self._one_done) def _decompress(self, fd, dir, dest): """decompress one entry dir can be a regexp""" logger.debug("Extracting to {}".format(dest)) # we temporarily extract to this destination the archive content tempdest = tempfile.mktemp(dir=dest) # We don't use shutil to automatically select the right codec as we need to ensure that zipfile # will keep the original perms. archive = None is_archive = False try: try: # the fd isn't forcibly at position 0 (like in Unity3D where we offset the script part) archive = tarfile.open(fileobj=fd, mode='r|*') logger.debug("tar file") except tarfile.ReadError: archive = self.ZipFileWithPerm(fd.name) logger.debug("zip file") is_archive = True # This is a band aid: if extractall can't successfully extract the file, we perform another approach: # exec tar xf and hope for the best (tar binary seems to be more acceptive of slightly misformed # archives) try: archive.extractall(tempdest) except tarfile.ReadError: logger.debug("Trigger fallback direct tar execution") shutil.rmtree(tempdest) os.makedirs(tempdest) archive = subprocess.Popen(["tar", "xf", fd.name, "-C", tempdest]) archive.communicate() fd.close() except: # try to treat it as self-extractable, some format don't like being opened at the same time though, so link # it. # error out if we had a valid archive which had an issue extracting if is_archive: raise name = "{}.safe".format(fd.name) os.link(fd.name, name) fd.close() st = os.stat(name) os.chmod(name, st.st_mode | stat.S_IEXEC) archive = subprocess.Popen([name, "-o{}".format(tempdest)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) archive.communicate() logger.debug("executable file") os.remove(name) try: dir_path = glob(os.path.join(tempdest, dir))[0] except IndexError: raise BaseException("Couldn't find {} in tarball".format(dir)) for filename in os.listdir(dir_path): shutil.move(os.path.join(dir_path, filename), os.path.join(dest, filename)) shutil.rmtree(tempdest) def _one_done(self, future): """Callback that will be called once one decompress finishes. (will be wired on the constructor) """ result = self.DecompressResult(error=None) if future.exception(): logger.error("A decompression to {} failed: {}".format(future.tag_dest, future.exception()), exc_info=future.exception()) result = result._replace(error=str(future.exception())) logger.info("Decompression to {} finished".format(future.tag_dest)) self._decompressed[future.tag_fd] = result if len(self._orders) == len(self._decompressed): self._done() def _done(self): """Callback that will be called once all download finishes. uris of the temporary files will be passed on the wired callback """ logger.info("All pending decompression done to {} done.".format([self._orders[fd].dest for fd in self._orders])) self._done_callback(self._decompressed) ubuntu-make-16.11.1ubuntu1/umake/settings.py0000664000000000000000000000327613013560574015662 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os from xdg.BaseDirectory import xdg_data_home DEFAULT_INSTALL_TOOLS_PATH = os.path.expanduser(os.path.join(xdg_data_home, "umake")) DEFAULT_BINARY_LINK_PATH = os.path.expanduser(os.path.join(DEFAULT_INSTALL_TOOLS_PATH, "bin")) OLD_CONFIG_FILENAME = "udtc" CONFIG_FILENAME = "umake" LSB_RELEASE_FILE = "/etc/lsb-release" UMAKE_FRAMEWORKS_ENVIRON_VARIABLE = "UMAKE_FRAMEWORKS" from_dev = False def get_version(): '''Get version depending if on dev or released version''' version = open(os.path.join(os.path.dirname(__file__), 'version'), 'r', encoding='utf-8').read().strip() if not from_dev: return version import subprocess try: # use git describe to get a revision ref if running from a branch. Will append dirty if local changes version = subprocess.check_output(["git", "describe", "--tags", "--dirty"]).decode('utf-8').strip() except (subprocess.CalledProcessError, FileNotFoundError): version += "+unknown" return version ubuntu-make-16.11.1ubuntu1/setup.py0000775000000000000000000001242413013560574014056 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from distutils import cmd from distutils.command.install_data import install_data as _install_data from distutils.command.build import build as _build import gettext from glob import glob import os from setuptools import setup, find_packages import subprocess import umake # that initializes the gettext domain from umake.settings import get_version I18N_DOMAIN = gettext.textdomain() PO_DIR = os.path.join(os.path.dirname(os.curdir), 'po') def get_requirements(tag_to_detect=""): """Gather a list of requirements line per line from tag_to_detect to next tag. if tag_to_detect is empty, it will gather every requirement""" requirements = [] tag_detected = False with open("requirements.txt") as f: for line in f.read().splitlines(): if line.startswith("#") or line == "": tag_detected = False if line.startswith(tag_to_detect): tag_detected = True continue if tag_detected: requirements.append(line) print(requirements) return requirements # # add translation support # class build(_build): sub_commands = _build.sub_commands + [('build_trans', None)] def run(self): _build.run(self) class build_trans(cmd.Command): description = 'Compile .po files into .mo files' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): for filename in os.listdir(PO_DIR): if not filename.endswith('.po'): continue lang = filename[:-3] src = os.path.join(PO_DIR, filename) dest_path = os.path.join('build', 'locale', lang, 'LC_MESSAGES') dest = os.path.join(dest_path, I18N_DOMAIN + '.mo') if not os.path.exists(dest_path): os.makedirs(dest_path) if not os.path.exists(dest): print('Compiling {}'.format(src)) subprocess.call(["msgfmt", src, "--output-file", dest]) else: src_mtime = os.stat(src)[8] dest_mtime = os.stat(dest)[8] if src_mtime > dest_mtime: print('Compiling {}'.format(src)) subprocess.call(["msgfmt", src, "--output-file", dest]) class install_data(_install_data): def run(self): for filename in os.listdir(PO_DIR): if not filename.endswith('.po'): continue lang = filename[:-3] lang_dir = os.path.join('share', 'locale', lang, 'LC_MESSAGES') lang_file = os.path.join('build', 'locale', lang, 'LC_MESSAGES', I18N_DOMAIN + '.mo') self.data_files.append((lang_dir, [lang_file])) _install_data.run(self) class update_pot(cmd.Command): description = 'Update template for translators' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): cmd = ['xgettext', '--language=Python', '--keyword=_', '--package-name', I18N_DOMAIN, '--output', 'po/{}.pot'.format(I18N_DOMAIN)] for path, names, filenames in os.walk(os.path.join(os.curdir, 'umake')): for f in filenames: if f.endswith('.py'): cmd.append(os.path.join(path, f)) subprocess.call(cmd) class update_po(cmd.Command): description = 'Update po from pot file' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): source_pot = os.path.join(os.curdir, 'po', '{}.pot'.format(I18N_DOMAIN)) for po_file in glob(os.path.join(os.curdir, 'po', '*.po')): subprocess.check_call(["msgmerge", "-U", po_file, source_pot]) setup( name="Ubuntu Make", version=get_version(), packages=find_packages(exclude=["tests*"]), package_data={}, entry_points={ 'console_scripts': [ 'umake = umake:main', 'udtc = umake:main' ], }, data_files=[ ('lib/python3/dist-packages/umake', ['umake/version']), ("share/ubuntu-make/log-confs", glob('log-confs/*.yaml')), ('share/zsh/vendor-completions', ['confs/completions/_umake']), ], # In addition to run all nose tests, that will as well show python warnings test_suite="nose.collector", cmdclass={ 'build': build, 'build_trans': build_trans, 'install_data': install_data, 'update_pot': update_pot, 'update_po': update_po, } ) ubuntu-make-16.11.1ubuntu1/bin/0000775000000000000000000000000013013560574013106 5ustar ubuntu-make-16.11.1ubuntu1/bin/umake0000775000000000000000000000203113013560574014132 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys # Run local umake from this helper root_dir = os.path.dirname(os.path.dirname(__file__)) sys.path.insert(0, root_dir) from umake import main # Stamp that we are running a local version from umake import settings settings.from_dev = True if __name__ == '__main__': main() ubuntu-make-16.11.1ubuntu1/enable_completion0000664000000000000000000000015413013560574015740 0ustar # just source that file to enable shell completion on umake eval "$(register-python-argcomplete bin/umake)" ubuntu-make-16.11.1ubuntu1/.travis.yml0000664000000000000000000000152413013560574014451 0ustar language: python sudo: required dist: trusty python: - "3.4" before_install: - sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make - sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make-builddeps - sudo apt-get update # install binary deps - sudo apt-get install -y $(tests/daily_runs/get_binary_depends ubuntu-make) # install tests requirements - sudo tests/daily_runs/install_build_tests_depends install: "" # we don't want to use virtualenv (see below) # as we can't use a system virtualenv anymore in travis CI and that # python-gobject isn't installable in pypy, we have to use system libraries # instead for both uncompiled and compiled modules. # The easiest way without hacking PYTHONPATH, PYTHONHOME is to use the system # python version by prepending it in the PATH. script: PATH="/usr/bin:$PATH" ./runtests pep8 small ubuntu-make-16.11.1ubuntu1/po/0000775000000000000000000000000013013560574012754 5ustar ubuntu-make-16.11.1ubuntu1/po/zh_CN.po0000664000000000000000000001747613013560574014334 0ustar # Chinese (Simplified) translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:12+0000\n" "Last-Translator: Didier Roche \n" "Language-Team: Chinese (Simplified) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* 命令 '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "在 Ubuntu 上轻松部署和设置开发环境" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "请注意,您还可以通过 LOG_CFG 指向的 yaml 配置文件来设置不同的调试日志行为。" #: umake/__init__.py:111 msgid "Show this help" msgstr "显示本帮助" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "提升输出的级别 (2级)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "如已安装指定框架,请卸载" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android 开发环境" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio 开发者环境" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android Studio" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "未安装,无法移除{}" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "如未提供默认框架名称,输出目录应包含斜杠 /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "如已安装框架,请卸载" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "未提供合适的答案" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "您的输入 '{}' 不是一个可以接受的选择。选项有:{}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "您的输入 '{}' 不是一个可以接受的选择。选项有:{} 和 {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "我接受" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "我不接受" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "是" #: umake/interactions/__init__.py:148 msgid "y" msgstr "y" #: umake/interactions/__init__.py:149 msgid "No" msgstr "否" ubuntu-make-16.11.1ubuntu1/po/eu.po0000664000000000000000000001644713013560574013741 0ustar # Basque translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:12+0000\n" "Last-Translator: Didier Roche \n" "Language-Team: Basque \n" "Language: eu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "Erakutsi laguntza hau" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Androiderako garapen-ingurunea" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio garapen-ingurunea" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android Studio" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Onartzen dut" #: umake/interactions/__init__.py:115 msgid "a" msgstr "o" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Ez dut onartzen" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "E" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Bai" #: umake/interactions/__init__.py:148 msgid "y" msgstr "b" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Ez" ubuntu-make-16.11.1ubuntu1/po/it.po0000664000000000000000000002016513013560574013734 0ustar # Italian translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-09-29 08:08+0000\n" "Last-Translator: Francesco \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Ubuntu make installazione di {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Comando '{}'" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Installa e configura facilmente un ambiente per sviluppatori su Ubuntu" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Nota che è anche possibile configurare diversi schemi di debug utilizzando " "LOG_CFG puntando ad un profilo di log yaml." #: umake/__init__.py:111 msgid "Show this help" msgstr "Mostra questo aiuto" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Aumenta la verbosità dell'output (2 livelli)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Rimuovi il framework specificato se installato" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:233 #, fuzzy msgid "PyCharm Educational Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:249 #, fuzzy msgid "PyCharm Professional Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Community Edition" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android Development Environment" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Ambiente di sviluppo Android Studio" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Non puoi rimuovere {} perchè non è installato" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Se non viene fornito il nome predefinito del framework, destdir dovrebbe " "contenere /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "RImuovi il framework se installato" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Nessuna risposta adeguata fornita" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "La tua scelta '{}' non è una scelta accettabile. Le scelte sono: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" "La tua scelta '{}' non è una scelta accettabile. Le scelte sono: {} e {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Accetto" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Non accetto" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Sì" #: umake/interactions/__init__.py:148 msgid "y" msgstr "y" #: umake/interactions/__init__.py:149 msgid "No" msgstr "No" ubuntu-make-16.11.1ubuntu1/po/id.po0000664000000000000000000002202413013560574013710 0ustar # Indonesian translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-03-01 08:40+0000\n" "Last-Translator: Eka Y Saputra \n" "Language-Team: Indonesian \n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-04-02 06:32+0000\n" "X-Generator: Launchpad (build 17413)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Instalasi Ubuntu make di {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Command '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Memasang dan mengatur lingkungan pengembangan dengan mudah di ubuntu" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Anda juga bisa mengonfigurasikan perilaku pencatatan debug yang berbeda " "menggunakan LOG_CFG yang merujuk ke sebuah profil pencatatan yaml" #: umake/__init__.py:111 msgid "Show this help" msgstr "Tampilkan bantuan ini" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Tingkatkan verbositas output (2 level)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Hapus framework yang ditentukan jika telah terinstal" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "IDE Generik" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Pure Eclipse Luna (4.4)" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "The Eclipse Luna Integrated Development Environment" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:233 #, fuzzy msgid "PyCharm Educational Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:249 #, fuzzy msgid "PyCharm Professional Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Community Edition" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 #, fuzzy msgid "PHP and web development IDE" msgstr "IDE untuk pengembangan game Stencyl" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 #, fuzzy msgid "You need to logout and login again for your installation to work" msgstr "" "Anda harus menjalankan sebuah sesi shell untuk membuat instalasi Anda bekerja" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Dartlang Development Environment" #: umake/frameworks/dart.py:49 #, fuzzy msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "Dart SDK with editor (default)" #: umake/frameworks/dart.py:56 #, fuzzy msgid "Dart SDK (default)" msgstr "Dart SDK with editor (default)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 #, fuzzy msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "Anda harus menjalankan sebuah sesi shell untuk membuat instalasi Anda bekerja" #: umake/frameworks/rust.py:43 #, fuzzy msgid "Rust language" msgstr "Bahasa Go" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 #, fuzzy msgid "Scala compiler and interpreter (default)" msgstr "Google compiler (default)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Bahasa Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Google compiler (default)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Lingkungan Pengembangan Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (default)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Lingkungan pengembangan Android Studio" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Anda tak bisa menghapus {} sebab belum pernah diinstal" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Jika nama framework bawaan tidak tersedia, destdir harus memuat sebuah /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Hapus framework jika terinstal" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Lingkungan Pengembangan Web" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Developer Edition" #: umake/frameworks/web.py:116 #, fuzzy msgid "Choose language: {}" msgstr "Bahasa Go" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora with Developer tools" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Lingkungan Pengembangan Game" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "IDE untuk pengembangan game Stencyl" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 #, fuzzy msgid "Unity3D Editor" msgstr "Dart Editor" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Tak ada jawaban yang cocok" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" "Entri '{}' Anda bukanlah pilihan yang bisa diterima. pilihannya adalah: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" "Entri '{}' Anda bukanlah pilihan yang bisa diterima. pilihannya adalah: {} " "dan {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Setuju" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Tidak setuju" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Ya" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Tidak" #~ msgid "Stencyl Game developer environment" #~ msgstr "Lingkungan pengembangan game Stencyl" #~ msgid "Dart Editor for the dart language" #~ msgstr "Dart Editor untuk bahasa Dart" ubuntu-make-16.11.1ubuntu1/po/ubuntu-make.pot0000664000000000000000000001575513013560574015752 0ustar # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "" ubuntu-make-16.11.1ubuntu1/po/sv.po0000664000000000000000000001722213013560574013750 0ustar # Swedish translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-05-02 09:00+0000\n" "Last-Translator: Lars Nyström \n" "Language-Team: Swedish \n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-05-04 07:08+0000\n" "X-Generator: Launchpad (build 17474)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Installera och konfigurera utvecklares arbetsmiljö enkelt på Ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "Visa denna hjälptext" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Avinstallera givet ramverk om det är installerat" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "Allmänna utvecklingsmiljöer" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 #, fuzzy msgid "PHP and web development IDE" msgstr "Stencyl spelutvecklingsmiljö" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Du kan inte avinstallera {} eftersom det inte är installerat" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Avinstallera ramverket om det är installerat" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Spelutvecklingsmiljö" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "Stencyl spelutvecklingsmiljö" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Inget lämpligt svar angivet" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Jag godkänner" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Jag godkänner inte" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Ja" #: umake/interactions/__init__.py:148 msgid "y" msgstr "j" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Nej" #~ msgid "Stencyl Game developer environment" #~ msgstr "Stencyl spelutvecklingsmiljö" ubuntu-make-16.11.1ubuntu1/po/pl.po0000664000000000000000000002167713013560574013744 0ustar # Polish translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-10-22 17:29+0000\n" "Last-Translator: Bartek Budzyński \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Instalacja {} przez Ubuntu make\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Komenda '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Łatwo wdróż i skonfiguruj środowisko programistyczne na Ubuntu" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Możesz również skonfigurować różne zachowania debug logów używając LOG_CFG " "wskazujących na profile logów yaml." #: umake/__init__.py:111 msgid "Show this help" msgstr "Wyświetla tę pomoc" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Zwiększ dokładność wyniku (2 stopnie)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Usuń wskazany framework, jeśli jest zainstalowany" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "generalne zintegrowane środowiska programistyczne" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "Zintegrowane środowisko programistyczne Eclipse Luna" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 #, fuzzy msgid "PHP and web development IDE" msgstr "" "deweloperskie zintegrowane środowisko programistyczne gier komputerowych - " "Stencyl" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 #, fuzzy msgid "You need to logout and login again for your installation to work" msgstr "" "Musisz ponownie uruchomić sesję powłoki do poprawnego działania instalacji" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 #, fuzzy msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "Dart SDK z edytorem" #: umake/frameworks/dart.py:56 #, fuzzy msgid "Dart SDK (default)" msgstr "Dart SDK z edytorem" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 #, fuzzy msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "Musisz ponownie uruchomić sesję powłoki do poprawnego działania instalacji" #: umake/frameworks/rust.py:43 #, fuzzy msgid "Rust language" msgstr "Język Go" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 #, fuzzy msgid "Scala compiler and interpreter (default)" msgstr "Kompilator Google (domyślnie)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Język Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Kompilator Google (domyślnie)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Środowisko Programistyczne Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (domyślnie)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "środowisko programistyczne Android Studio" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Nie możesz usunąć {}, ponieważ nie jest zainstalowane" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Jeśli nazwa domyślnego frameworka nie jest określona, destdir powinien " "zawierać a /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Usuń framework, jeśli jest zainstalowany" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Internetowe środowisko deweloperskie" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Deweloperska Edycja Firefox" #: umake/frameworks/web.py:116 #, fuzzy msgid "Choose language: {}" msgstr "Język Go" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora z narzędziami deweloperskimi" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Środowiska Deweloperskie Gier Komputerowych" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" "deweloperskie zintegrowane środowisko programistyczne gier komputerowych - " "Stencyl" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 #, fuzzy msgid "Unity3D Editor" msgstr "Edytor Dart" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Nie podano właściwej odpowiedzi" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Twój wybór '{}' nie jest dopuszczalny. Możliwe wybory to: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Twój wybór '{}' nie jest dopuszczalny. Możliwe wybory to: {} i {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Zgadzam się" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Nie zgadzam się" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Tak" #: umake/interactions/__init__.py:148 msgid "y" msgstr "T" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Nie" #~ msgid "Stencyl Game developer environment" #~ msgstr "środowisko deweloperskie gier komputerowych - Stencyl" ubuntu-make-16.11.1ubuntu1/po/en_GB.po0000664000000000000000000001650213013560574014272 0ustar # English (United Kingdom) translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:09+0000\n" "Last-Translator: destiriser \n" "Language-Team: English (United Kingdom) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Deploy and setup developers environment easily on Ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Your entry '{}' isn't an acceptable choice. Choices are: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Your entry '{}' isn't an acceptable choice. Choices are: {} and {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "I accept" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "" ubuntu-make-16.11.1ubuntu1/po/zh_TW.po0000664000000000000000000002204113013560574014346 0ustar # Chinese (Traditional) translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-05-03 05:28+0000\n" "Last-Translator: V字龍(Vdragon) \n" "Language-Team: Chinese (Traditional) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-05-04 07:08+0000\n" "X-Generator: Launchpad (build 17474)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# {} 的 Ubuntu make 安裝\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* 命令「{}」:" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "在 Ubuntu 上輕易地佈署與安裝開發環境" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "注意您也可以使用 LOG_CFG 環境變數指向一個 YAML 格式除錯紀錄設定檔來設定不同的" "除錯紀錄行為。" #: umake/__init__.py:111 msgid "Show this help" msgstr "顯示此幫助訊息" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "增加輸出訊息的冗長程度(最多可提高 2 級)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "如果已被安裝的話移除指定的軟體框架" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "一般整合式開發環境" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "純粹的 Eclipse Luna (4.4) 整合式開發環境" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "Eclipse Luna 整合式開發環境" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna 整合式開發環境" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm 社群版本" #: umake/frameworks/ide.py:233 #, fuzzy msgid "PyCharm Educational Edition" msgstr "PyCharm 社群版本" #: umake/frameworks/ide.py:249 #, fuzzy msgid "PyCharm Professional Edition" msgstr "PyCharm 社群版本" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA 社群版本" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 #, fuzzy msgid "PHP and web development IDE" msgstr "Stencyl 遊戲開發者整合式開發環境" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 #, fuzzy msgid "You need to logout and login again for your installation to work" msgstr "您必須重新啟動殼程式(shell)工作階段您的安裝才會生效" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Dartlang 開發環境" #: umake/frameworks/dart.py:49 #, fuzzy msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "Dart 軟體開發工具(SDK)與編輯器(預設)" #: umake/frameworks/dart.py:56 #, fuzzy msgid "Dart SDK (default)" msgstr "Dart 軟體開發工具(SDK)與編輯器(預設)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 #, fuzzy msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "您必須重新啟動殼程式(shell)工作階段您的安裝才會生效" #: umake/frameworks/rust.py:43 #, fuzzy msgid "Rust language" msgstr "Go 程式語言" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 #, fuzzy msgid "Scala compiler and interpreter (default)" msgstr "Google 編譯器(預設)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Go 程式語言" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Google 編譯器(預設)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android 開發環境" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio(預設)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio 軟體開發環境" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "您不能移除 {} 因為它沒有被安裝" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "如果軟體框架已經被安裝的話移除它" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Web 開發環境" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox 開發版" #: umake/frameworks/web.py:116 #, fuzzy msgid "Choose language: {}" msgstr "Go 程式語言" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "內建開發工具的 Firefox Aurora" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "遊戲開發環境" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "Stencyl 遊戲開發者整合式開發環境" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 #, fuzzy msgid "Unity3D Editor" msgstr "Dart 編輯器" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "沒有得到適當的答案" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "您的「{}」輸入並不是個可接受的選項。可用選項有:{}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "您的「{}」輸入並不是個可接受的選項。可用選項有:{} 與 {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "我接受" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "我不接受" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "是" #: umake/interactions/__init__.py:148 msgid "y" msgstr "y" #: umake/interactions/__init__.py:149 msgid "No" msgstr "否" #~ msgid "Stencyl Game developer environment" #~ msgstr "Stencyl 遊戲開發環境" #~ msgid "Dart Editor for the dart language" #~ msgstr "用於 Dart 語言的 Dart 編輯器" ubuntu-make-16.11.1ubuntu1/po/da.po0000664000000000000000000001633013013560574013703 0ustar # Danish translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-04-28 19:25+0000\n" "Last-Translator: Aputsiaĸ Niels Janussen \n" "Language-Team: Danish \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-05-04 07:08+0000\n" "X-Generator: Launchpad (build 17474)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "Vis denne hjælp" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Jeg accepterer" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Ja" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Nej" ubuntu-make-16.11.1ubuntu1/po/fr.po0000664000000000000000000002314013013560574013723 0ustar # French translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-11-23 15:36+0000\n" "Last-Translator: Didier Roche \n" "Language-Team: French \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-24 07:00+0000\n" "X-Generator: Launchpad (build 17850)\n" "Language: fr\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Ajouté par Ubuntu make de {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Commande '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" "Installez et déployez un environnement de développement facilement sur ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Il est également possible de configurer différents comportements et niveaux " "de logs en faisant pointer la variable d'environnement LOG_CFG vers un " "fichier de profile de log yaml." #: umake/__init__.py:111 msgid "Show this help" msgstr "Afficher cette aide" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Augmenter la verbosité de la sortie (2 niveaux)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Supprimer l'environnement spécifié si installé" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "Afficher la version et quitter" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "Environnement de développement intégré" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Eclipse Luna (4.4)" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "L'environnement de développement intégré Eclipse Luna" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Édition Communautaire" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "PyCharm Édition Éducation" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "PyCharm Édition Professionelle" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Édition Communautaire" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "IDE Ruby on Rails" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" "IDE pour le développement d'applications javascript clientes et serveur" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "IDE pour PHP et web" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "IDE C/C++ CLion" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "Logiciels pour Arduino" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "IDE pour Arduino" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "Arduino" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" "Vous devez vous déconnecter et vous reconnecter pour que votre installation " "fonctionne" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "IDE Netbeans" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Environnement de Développement Dartlang" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "Dart SDK avec éditeur (non supporté par upstream)" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "Dart SDK (défault)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "Vous devez redémarrer votre shell courant pour que votre installation {} " "fonctionne correctement" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "Langage Rust" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "Distribution officielle Rust" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "Langage Scala" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "Compilateur et interpréteur Scala (défaut)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Langage Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Compilateur Google (défaut)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Environnement de développement Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (défaut)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Environnement de développement Android Studio" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "SDK Android" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" "Un framework par défaut pour la catégorie {} est requis, mais il n'y en " "a aucun" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "Vous ne pouvez pas installer ce framework sur cette machine" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Vous ne pouvez supprimer {} puisqu'il n'est pas installé" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Si l'environnement par défaut n'est pas spécifié, destdir doit contenir un /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Supprime l'environnement si installé" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "Accepter la license sans demander" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Environnement de développement Web" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Édition Développeur" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "Votre langue : {}" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora avec outils développeur" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "Installer dans la lange choisie sans demander" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "Visual Studio pour le web moderne et cloud" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "Visual Studio Code" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Environnement de développement de jeux" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "Éditeur de jeux Stencyl" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "Éditeur Unity 3D avec support expérimental pour Linux" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "Éditeur Unity 3D" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "Outil Twine de création interactive et non linéaire d'histoires" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "Twine" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "La réponse n'est pas satisfaisante" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" "Votre entrée '{}' n'est pas un choix acceptable. Choisissez parmi: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" "Votre entrée '{}' n'est pas un choix acceptable. Choisissez entre {} et {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "J'accepte" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Je ne les accepte pas" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Oui" #: umake/interactions/__init__.py:148 msgid "y" msgstr "o" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Non" ubuntu-make-16.11.1ubuntu1/po/en_CA.po0000664000000000000000000001646213013560574014272 0ustar # English (Canada) translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:09+0000\n" "Last-Translator: destiriser \n" "Language-Team: English (Canada) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Deploy and setup developers environment easily on Ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Your entry '{}' isn't an acceptable choice. Choices are: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Your entry '{}' isn't an acceptable choice. Choices are: {} and {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "I accept" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "" ubuntu-make-16.11.1ubuntu1/po/te.po0000664000000000000000000002166713013560574013740 0ustar # Telugu translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:12+0000\n" "Last-Translator: Didier Roche \n" "Language-Team: Telugu \n" "Language: te\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# {} యొక్క Ubuntu make ఇన్స్టాలేషన్\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* ఆదేశం '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "సులభంగా డెవలపర్ల ఎన్విరాన్‌మెంట్‌ని సెటప్ చెయ్యి" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "LOG_CFG ని ఏదైనా ఒక yaml ప్రొఫైల్‌ని సూచించేటట్టు చేయడం ద్వారా డీబగ్గింగ్ లాగ్‌ల పని విధానాన్ని మార్చవచ్చు" #: umake/__init__.py:111 msgid "Show this help" msgstr "ఈ సహాయాన్ని చూపించు" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "ఎక్కువ సమాచారాన్ని చూపించు (రెండు రెట్లు)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "ఫ్రేమ్‌వర్క్ ఇన్స్టాల్ అయి వుంటే తొలగించండి" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "ఆండ్రాయిడ్ డెవలెప్‌మెంట్ ఎన్విరాన్‌మెంట్" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "ఆండ్రాయిడ్ స్ట్యూయో" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "ఆండ్రాయిడ్ స్తూడియో డెవలపర్ ఎన్విరాన్‌మెంట్" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "ఆండ్రాయిడ్ స్ట్యూయో" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "{} ఇన్స్టాల్ అయి లేదు కాబట్టి దానిని తొలగించలేము" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "ఫ్రేమ్‌వర్క్ ఇన్స్టాల్ అయి వుంటే దానిని తొలగించు" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "తగిన సమాధానం ఇవ్వలేదు" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "మీ ఎంపిక '{}' తగినది కాదు. సరియైన ఎంపికలు: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "మీ ఎంపిక '{}' తగినది కాదు. సరియైన ఎంపికలు: {} మరియు {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "నాకు అంగీకారమే" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "నేను అంగీకరించను" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "అవును" #: umake/interactions/__init__.py:148 msgid "y" msgstr "అవును" #: umake/interactions/__init__.py:149 msgid "No" msgstr "కాదు" ubuntu-make-16.11.1ubuntu1/po/hr.po0000664000000000000000000001656713013560574013744 0ustar # Croatian translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:12+0000\n" "Last-Translator: Didier Roche \n" "Language-Team: Croatian \n" "Language: hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Naredba '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "Prikaži ovu pomoć" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio razvojno okruženje" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android Studio" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Nije ponuđen prikladan odgovor" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Vaš unos '{}' nije prikladan. Mogući unosi su: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Vaš unos '{}' nije prikladan. Mogući unosi su: {} i {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Prihvaćam" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Ne prihvaćam" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Da" #: umake/interactions/__init__.py:148 msgid "y" msgstr "d" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Ne" ubuntu-make-16.11.1ubuntu1/po/zh_HK.po0000664000000000000000000001656313013560574014332 0ustar # Chinese (Hong Kong) translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:12+0000\n" "Last-Translator: Anthony Wong \n" "Language-Team: Chinese (Hong Kong) \n" "Language: zh_HK\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* 命令 '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "在 Ubuntu 上輕鬆部署和配置開發環境" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "顯示此求助說明" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "提升輸出詳細級別 (2級)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android 開發環境" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio 開發環境" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android Studio" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "未提供合適答案" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "接受" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "不接受" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "" ubuntu-make-16.11.1ubuntu1/po/en_AU.po0000664000000000000000000001647013013560574014313 0ustar # English (Australia) translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2014-12-09 13:09+0000\n" "Last-Translator: destiriser \n" "Language-Team: English (Australia) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Deploy and setup developers environment easily on Ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Your entry '{}' isn't an acceptable choice. Choices are: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Your entry '{}' isn't an acceptable choice. Choices are: {} and {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "I accept" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "" ubuntu-make-16.11.1ubuntu1/po/fa.po0000664000000000000000000001723713013560574013714 0ustar # Persian translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-07-23 05:28+0000\n" "Last-Translator: Arash Badie Modiri \n" "Language-Team: Persian \n" "Language: fa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" #: umake/__init__.py:111 msgid "Show this help" msgstr "این راهنما را نشان بده" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 #, fuzzy msgid "Rust language" msgstr "زبان Go" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "زبان Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "محیط توسعه Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "نمی‌توانید «{}» را پاک کنید چون اصلا نصب نشده" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "محیط توسعه وب" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "نسخه‌ی توسعه‌دهنده Firefox" #: umake/frameworks/web.py:116 #, fuzzy msgid "Choose language: {}" msgstr "زبان Go" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "نسخه‌ی Aurora مرورگر Firefox به همراه ابزار توسعه" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "محیط توسعه‌ی بازی" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "پاسخ مناسبی داده نشد" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "«{}» ورودی قابل قبولی نیست. انتخاب‌ها «{}» و «{}»اند" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr "" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "" #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "قبول می‌کنم" #: umake/interactions/__init__.py:115 msgid "a" msgstr "" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "قبول نمی‌کنم" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "" #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "بلی" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "خیر" ubuntu-make-16.11.1ubuntu1/po/ru.po0000664000000000000000000002666213013560574013756 0ustar # Russian translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-11-17 21:34+0300\n" "Last-Translator: Eldar Khayrullin \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Poedit 1.7.7\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Ubuntu make установка {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Команда '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Легкое развертывание и установка среды разработчика на ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Обратите внимание, что вы также можете настроить различное поведение ведения " "журнала отладки используя LOG_CFG, который указывает на профиль журнала yaml." #: umake/__init__.py:111 msgid "Show this help" msgstr "Показать эту справку" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Увеличить многословность выхода (2 уровня)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Удалить указанную среду, если она установлена" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "Напечатать версию и выйти" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "Общие интегрированные среды разработки" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Чистый Eclipse Luna (4.4)" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "Интегрированная среда разработки Eclipse Luna" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Общественная версия" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "PyCharm Учебная версия" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "PyCharm Профессиональная версия" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Общественная версия" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "Ruby в интегрированной среде разработки Rails" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" "Полная клиентская и серверная интегрированная среда разработки javascript" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "Интегрированная среда разработки PHP и веб" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "Интегрированная среда разработки CLion языка C/C++" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "Распространение ПО Arduino" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "Интегрированная среда разработки ПО Arduino" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "Arduino" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "Вам нужно завершить сеанс и войти снова для установки к работе" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "Интегрированная среда разработки Netbeans" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Среда разработки Dartlang" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" "Комплект средств разработки Dart с редактором (больше не поддерживается)" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "Комплект средств разработки Dart" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "Вам нужно перезапустить вашу текущую сессию оболочки для установки {} к " "работе правильно" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "Язык Rust" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "Официальная поставка Rust" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "Язык программирования Scala" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "Компилятор и интерпретатор Scala (по умолчанию)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Язык Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Компилятор Google (по умолчанию)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Среда разработки Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (по умолчанию)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Среда разработки Android Studio" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "Комплект средств разработки Android" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Родной комплект разработки Android" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "Среда по умолчанию для категории {} была запрошена там где ее нет" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "Вы не можете установить эту среду на этой машине" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Вы не можете удалить {}, поскольку он не установлен" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Если имя среды по умолчанию не предусмотрено, директория назначения должна " "содержать /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Удалить среду, если установлена" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "Принять лицензию без запроса" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Веб среда разработки" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Версия разработчика" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "Выбрать язык: {}" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora с инструментами разработчика" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "Установить в данном языке без запроса" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" "Visual Studio фокусируется на разработке современных веб и облачных " "приложений" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "Visual Studio Code" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Окружение разработки игр" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "Интегрированная среда разработки разработчика игр Stencyl" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "Unity 3D Editor Linux экспериментальная поддержка" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "Редактор Unity3D" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "Инструмент для создания интерактивных и нелинейных историй Twine" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "Twine" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Не указано приемлемого ответа" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Ваш запись '{}' не является приемлемым выбором. возможные варианты: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" "Ваш запись '{}' не является приемлемым выбором. возможные варианты: {} и {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Я принимаю" #: umake/interactions/__init__.py:115 msgid "a" msgstr "п" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Я не принимаю" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "Н" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Да" #: umake/interactions/__init__.py:148 msgid "y" msgstr "д" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Нет" ubuntu-make-16.11.1ubuntu1/po/el.po0000664000000000000000000002407013013560574013717 0ustar # Greek translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-05-03 22:41+0000\n" "Last-Translator: stratosg \n" "Language-Team: Greek \n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-05-04 07:08+0000\n" "X-Generator: Launchpad (build 17474)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Το Ubuntu εγκαθιστά το {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Εντολή '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" "Αναπτύξτε και ρυθμίστε το προγραμματιστικό περιβάλλον εύκολα στο ubuntu" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Σημειώστε πως μπορείτε επίσης να ρυθμίστε διαφορετικές συμπεριφορές " "καταγραφών απασφαλμάτωσης χρησιμοποιώντας LOG_CFG δείχνοντας σε ένα log yaml " "προφίλ" #: umake/__init__.py:111 msgid "Show this help" msgstr "Εμφάνιση αυτής της βοήθειας" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Αυξήστε τη λεκτική λεπτομέρεια εξόδου (2 επίπεδα)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Αφαίρεση συγκεκριμένου πλάισιου αν έχει εγκατασταθεί" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "Γενικά IDE" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Έκδοση Κοινότητας" #: umake/frameworks/ide.py:233 #, fuzzy msgid "PyCharm Educational Edition" msgstr "PyCharm Έκδοση Κοινότητας" #: umake/frameworks/ide.py:249 #, fuzzy msgid "PyCharm Professional Edition" msgstr "PyCharm Έκδοση Κοινότητας" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Έκδοση Κοινότητας" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 #, fuzzy msgid "PHP and web development IDE" msgstr "IDE προγραμματιστή παιχνιδιών Stencyl" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 #, fuzzy msgid "You need to logout and login again for your installation to work" msgstr "" "Πρέπει να επανεκκινήσεις μια συνεδρία κελύφους για να δουλέψει η εγκατάστασή " "σου" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Dartlang Περιβάλλον Ανάπτυξης" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "" #: umake/frameworks/dart.py:56 #, fuzzy msgid "Dart SDK (default)" msgstr "Android Στούντιο (προεπιλεγμένο)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 #, fuzzy msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "Πρέπει να επανεκκινήσεις μια συνεδρία κελύφους για να δουλέψει η εγκατάστασή " "σου" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 #, fuzzy msgid "Scala compiler and interpreter (default)" msgstr "Google μεταγλωττιστής (προεπιλεγμένος)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Google μεταγλωττιστής (προεπιλεγμένος)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android Περιβάλλον Ανάπτυξης" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Στούντιο (προεπιλεγμένο)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Στούντιο" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Περιβάλλον προγραμματιστή Android Στούντιο" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Δεν μπορείς να αφαιρέσει {} ενώ δεν είναι εγκατεστημένο" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Εάν το προεπιλεγμένο όνομα πλαισίου δεν παρέχεται, το destdir πρέπει να " "περιέχει ένα /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Αφαιρέστε το πλάισιο αν είναι εγκατεστημένο" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Περιβάλλον Ανάπτυξης Ιστού" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Έκδοση Προγραμματιστή" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora με εργαλεία Προγραμματιστή" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Περιβάλλον Ανάπτυξης Παιχνιδιών" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "IDE προγραμματιστή παιχνιδιών Stencyl" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Δεν παρέχεται καμία καμία κατάλληλη απάντηση" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "" "Η καταχώρισή σας '{}' δεν ειναι μια αποδεκτή επιλογή. οι επιλογές είναι: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "" "Η καταχώρισή σας '{}' δεν είναι μια αποδεκτή επιλογή. οι επιλογές είναι: {} " "και {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Αποδέχομαι" #: umake/interactions/__init__.py:115 msgid "a" msgstr "α" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Δεν αποδέχομαι" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Ναι" #: umake/interactions/__init__.py:148 msgid "y" msgstr "" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Όχι" #~ msgid "Stencyl Game developer environment" #~ msgstr "Περιβάλλον προγραμματιστή Παιχνιδιών Stencyl" ubuntu-make-16.11.1ubuntu1/po/es.po0000664000000000000000000002322113013560574013723 0ustar # Spanish translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2016-09-24 22:34-0400\n" "Last-Translator: Wilsen Hernandez \n" "Language-Team: Spanish \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-04-02 06:32+0000\n" "X-Generator: Poedit 1.8.7.1\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Instalación de {} con Ubuntu make\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Orden «{}»:" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Instalar y configurar entornos de desarrollo fácilmente en Ubuntu" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "También puede configurar distintos comportamientos para los registros de " "depuración usando LOG_CFG apuntando a un perfil yaml." #: umake/__init__.py:111 msgid "Show this help" msgstr "Muestra esta ayuda" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Aumentar detalles en la salida (2 niveles)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Eliminar el marco especificado si está instalado" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "Mostrar versión y salir" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "EID genéricos" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Pure Eclipse Luna (4.4)" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "El entorno integrado de desarrollo Eclipse Luna" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Edición Comunidad" #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "PyCharm Edición Educacional" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "PyCharm Edición Profesional" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Community Edition" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "EID Ruby on Rails" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "Complejo EID para cliente y servidor" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "EID de desarrollo web y PHP" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "EID de C/C++ integrado CLion" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "La Distribución de Software Arduino" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "EID Arduino Software" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "Arduino" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" "Es necesario reiniciar la sesión del equipo para que la instalación entre en " "funcionamiento" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "EID Netbeans" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Entorno de desarrollo Dartlang" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "SDK de Dart con editor (subida ya no soportada)" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "SDK de Dart con editor (predeterminado)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "Es necesario reiniciar la sesión de la consola para que la instalación entre " "en funcionamiento" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "Lenguaje Rust" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "La distribución oficial de Rust" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "Lenguaje de Programación Scala" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "Compilador e interpretador Scala (predeterminado)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Lenguaje Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Compilador de Google (predeterminado)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Entorno de desarrollo de Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (predeterminado)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Entorno de desarrollo Android Studio" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "Android SDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" "Se solicito un marco predeterminado para la categoría {} y no existe alguno" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "No puedes instalar ese marco predeterminado en esta maquina" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "No se puede desinstalar {} ya que no está instalado" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Si no se especifica el nombre del marco predeterminado, destdir debe " "contener una /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Eliminar marco si está instalado" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "Aceptar licencia sin preguntar" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Entorno de desarrollo web" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Developer Edition" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "Elige idioma: {}" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora con herramientas de desarrollo" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "Instalar en el idioma dado sin preguntar" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "Visual Studio enfocado a la web moderna y la nube" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "Visual Studio Code" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Entorno de desarrollo de juegos" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "EID de desarrollo de juegos Stencyl" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "Editor Unity 3D soporte experimental Linux" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "Editor Unity 3D" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "Herramienta Twine para crear historia interactivas y no-lineales" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "Twine" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "No se ha provisto una respuesta adecuada" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Su entrada «{}» no es una opción aceptable. Las opciones son: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Su entrada «{}» no es una opción aceptable. Las opciones son: {} y {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Acepto" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "No acepto" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Sí" #: umake/interactions/__init__.py:148 msgid "y" msgstr "s" #: umake/interactions/__init__.py:149 msgid "No" msgstr "No" #~ msgid "Stencyl Game developer environment" #~ msgstr "Entorno de desarrollo de juegos Stencyl" #~ msgid "Dart Editor for the dart language" #~ msgstr "Editor Dart para el lenguaje Dart" ubuntu-make-16.11.1ubuntu1/po/tr.po0000664000000000000000000002273213013560574013747 0ustar # Turkish translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-04-24 08:17+0000\n" "Last-Translator: Julian & Mehmet \n" "Language-Team: Turkish \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-05-04 07:08+0000\n" "X-Generator: Launchpad (build 17474)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "{}\n'in Ubuntu make kurulumu" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Komut '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Ubuntuda dağıtım ve kurulum geliştiricileri ortamını kolayca yapabilirsiniz" #: umake/__init__.py:108 msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Ayrıca farklı hata ayıklama logu davranış yapılandırabileceğiniz kullanarak " "LOG_CFG bir log yaml profilini işaret eder." #: umake/__init__.py:111 msgid "Show this help" msgstr "Bu yardımı göster" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Çıkış ayrıntısını arttırma (2 seviye)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Eğer yüklü ise belirtilen çerçeveyi kaldır" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "Sürümü yaz ve çık" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "Genel IDEler" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Pure Eclipse Luna (4.4)" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "Eclipse Luna " #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna Tümleşik Geliştirme Ortamı (IDE)" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Topluluk Sürümü " #: umake/frameworks/ide.py:233 msgid "PyCharm Educational Edition" msgstr "PyCharm Eğitim Sürümü" #: umake/frameworks/ide.py:249 msgid "PyCharm Professional Edition" msgstr "PyCharm Profesyonel Sürümü" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Topluluk Sürümü" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "Ruby on Rails IDE" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "Kompleks istemci-tarası ve server-tarafı javascript IDE" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "PHP ve web geliştirme IDEsi" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "CLion entegrelenmiş C/C++ IDE" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "Arduino Yazılım Dağıtımı" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "Arduino Yazılım IDEsi" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "Arduino" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "Kurulumunuzun çalışabilmesi için tekrar çıkış ve giriş yapmaya ihtiyacınız vardır" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "Netbeans IDE" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Dartlang Geliştirme Ortamı" #: umake/frameworks/dart.py:49 msgid "Dart SDK with editor (not supported upstream anymore)" msgstr "Düzenleyici ile Dart SDK (bundan sonra güncellemeleri desteklenmeyecek)" #: umake/frameworks/dart.py:56 msgid "Dart SDK (default)" msgstr "Dart SDK (varsayılan)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" "{} Kurulumunun düzgün çalışabilmesi için geçerli kabuk oturumunuzun " "tekrar başlatılmasına ihtiyaç vardır" #: umake/frameworks/rust.py:43 msgid "Rust language" msgstr "Rust dili" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "Resmi Rust Dağıtımı" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "Scala Programlama Dili" #: umake/frameworks/scala.py:46 msgid "Scala compiler and interpreter (default)" msgstr "Scala derleyici ve yorumlayıcı (varsayılan)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Go dili" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Google derleyicisi (varsayılan)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android Geliştirme Ortamı" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (varsayılan)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio geliştirici ortamı" #: umake/frameworks/android.py:111 msgid "Android SDK" msgstr "Android SDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "Hiçbiri yoksa {} kategorisi için varsayılan çerçeve talep edilmiştir" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "Bu makinaya bu çerçeveyi kuramayabilirsiniz" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "{} kurulmamış iken kaldıramazsınız" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Varsayılan çerçevenin adı sağlamıyorsa, hedefdizin bir / içermelidir" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Kurulmuşsa çerçeveyi kaldır" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "Lisansı telkinsiz kabul et" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Web Geliştirme Ortamı" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Geliştirici Sürümü" #: umake/frameworks/web.py:116 msgid "Choose language: {}" msgstr "Bir dil seçiniz: {}" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora ile Geliştirici araçları" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "Verilen dili telkinsiz kur" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "Visual Studio moden web ve bulut'a odaklanmıştır" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "Visual Studio Kodu" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Oyun Geliştirme Ortamları" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "Stencyl oyun geliştirici IDEsi" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "Unity 3D Editörü Linux deneysel desteği" #: umake/frameworks/games.py:154 msgid "Unity3D Editor" msgstr "Unity3D Editörü" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "Etkileşimli ve nonlineer hikayeleri oluşturma için Twine aracı" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "Twine" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Uygun cevap sağlanmamıştır" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. Choices are: {}" msgstr "Sizin girişiniz '{}' kabul edilebilir bir seçim değildir. Seçimler: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. Choices are: {} and {}" msgstr "Sizin girişiniz '{}' kabul edilebilir bir seçim değildir. Seçimler: {} ve {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Kabul ediyorum" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Kabul etmiyorum" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Evet" #: umake/interactions/__init__.py:148 msgid "y" msgstr "y" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Hayır" ubuntu-make-16.11.1ubuntu1/po/pt_BR.po0000664000000000000000000002344613013560574014333 0ustar # Brazilian Portuguese translation for ubuntu-make # Copyright (c) 2015 Rosetta Contributors and Canonical Ltd 2015 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2015. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-07-13 13:02+0000\n" "Last-Translator: Renato Cruz \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Ubuntu make instalação de {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Comando '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "" "Instala e configura de maneira fácil um ambiente de desenvolvimento no Ubuntu" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Note que você também pode configurar diferentes comportamentos para os logs " "de depuração usando LOG_CFG e apontando o log para o arquivo yaml." #: umake/__init__.py:111 msgid "Show this help" msgstr "Mostrar ajuda" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Aumenta a verbosidade da saída (2 níveis)" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Remove um determinado framework se estiver instalado" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "Exibir versão e sair" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "IDEs genéricas" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Eclipse Luna (4.4) puro" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "Ambiente de Desenvolvimento Integrado Eclipse Luna" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:233 #, fuzzy msgid "PyCharm Educational Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:249 #, fuzzy msgid "PyCharm Professional Edition" msgstr "PyCharm Community Edition" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Community Edition" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "Ruby on Rails IDE" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "IDE Javascript lado cliente e lado servidor" #: umake/frameworks/ide.py:331 #, fuzzy msgid "PHP and web development IDE" msgstr "IDE PHP e desenvolvimento web" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "IDE Clion integrado C/C++" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "Distribuição de software Arduino" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "IDE Software Arduino" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "Arduino" #: umake/frameworks/ide.py:484 #, fuzzy msgid "You need to logout and login again for your installation to work" msgstr "Você precisa reiniciar a sessão shell para que sua instalação funcione" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "Netbeans IDE" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Ambiente de desenvolvimento Dartlang" #: umake/frameworks/dart.py:49 #, fuzzy msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "Dart SDK com editor (sem suporte upstream)" #: umake/frameworks/dart.py:56 #, fuzzy msgid "Dart SDK (default)" msgstr "Dart SDK com editor (padrão)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 #, fuzzy msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "Você precisa reiniciar a sessão shell para que sua instalação funcione" #: umake/frameworks/rust.py:43 #, fuzzy msgid "Rust language" msgstr "Linguagem Go" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "Distribuição official Rust" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "Linguagem de programação Scala" #: umake/frameworks/scala.py:46 #, fuzzy msgid "Scala compiler and interpreter (default)" msgstr "Compilador e interpretador Scala (padrão)" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Linguagem Go" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Compilador Google (padrão)" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Ambiente de desenvolvimento Android" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio (padrão)" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Ambiente de desenvolvimento Android Studio" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android SDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "Um framework padrão é necessário para a categoria {} quando não existe nenhum" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "Você não pode instalar esse framework neste computador" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "Você não pode remover {} porque ele não está instalado" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Se o nome padrão do framework não for fornecido, o diretório de destino deve " "conter uma /" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Remove o framework se estiver instalado" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "Aceitar licença sem avisos" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Ambiente para desenvolvimento Web" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Developer Edition" #: umake/frameworks/web.py:116 #, fuzzy msgid "Choose language: {}" msgstr "Escolha a linguagem: {}" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora com ferramentas para desenvolvedores" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "Instalar em dada linguagem sem avisos" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "Visual Studio focado em web moderna e Cloud" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "Visual Studio Code" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Ambiente para desenvolvimento de jogos" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "IDE Stencyl para desenvolvimento de jogos" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "Unity 3D Editor Linux suporte experimental" #: umake/frameworks/games.py:154 #, fuzzy msgid "Unity3D Editor" msgstr "Editor Unity3D" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "Ferramenta Twine para criar histórias interativas e não lineares" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "Twine" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Não há resposta adequada" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "A sua entrada '{}' não é uma opção aceitável, as opções são: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "A sua entrada '{}' não é uma opção aceitável, as opções são: {} e {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{}[{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Eu aceito" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Eu não aceito" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{}({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Sim" #: umake/interactions/__init__.py:148 msgid "y" msgstr "s" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Não" #~ msgid "Stencyl Game developer environment" #~ msgstr "Ambiente para desenvolvimento de jogos Stencyl" #~ msgid "Dart Editor for the dart language" #~ msgstr "Editor Dart para a linguagem dart" ubuntu-make-16.11.1ubuntu1/po/de.po0000664000000000000000000002157513013560574013716 0ustar # German translation for ubuntu-make # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the ubuntu-make package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: ubuntu-make\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-17 09:26+0100\n" "PO-Revision-Date: 2015-10-27 10:42+0000\n" "Last-Translator: Oliver Jakobi \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2015-11-05 13:56+0000\n" "X-Generator: Launchpad (build 17838)\n" #: umake/tools.py:48 msgid "# Ubuntu make installation of {}\n" msgstr "# Ubuntu make Installation von {}\n" #: umake/__init__.py:99 msgid "* Command '{}':" msgstr "* Befehl '{}':" #: umake/__init__.py:107 msgid "Deploy and setup developers environment easily on ubuntu" msgstr "Entwicklerumgebungen einfach auf Ubuntu aufspielen und konfigurieren" #: umake/__init__.py:108 #, fuzzy msgid "" "Note that you can also configure different debug logging behavior using " "LOG_CFG that points to a log yaml profile." msgstr "" "Beachten Sie, dass ebenfalls das Verhalten verschiedener \"debug logs\" " "konfiguriert werden kann, indem Sie LOG_CFG benutzen, was auf einen \"log " "yaml\"-Profil zeigt." #: umake/__init__.py:111 msgid "Show this help" msgstr "Diese Hilfe anzeigen" #: umake/__init__.py:112 msgid "Increase output verbosity (2 levels)" msgstr "Erhöhe die Ausführlichkeit der Ausgabe" #: umake/__init__.py:114 msgid "Remove specified framework if installed" msgstr "Entferne, falls installiert, das spezifizierte Framework" #: umake/__init__.py:116 msgid "Print version and exit" msgstr "" #: umake/frameworks/ide.py:63 msgid "Generic IDEs" msgstr "Allgemeine integrierte Entwicklungsumgebungen" #: umake/frameworks/ide.py:76 msgid "Pure Eclipse Luna (4.4)" msgstr "Pure Eclipse Luna (4.4)" #: umake/frameworks/ide.py:128 msgid "The Eclipse Luna Integrated Development Environment" msgstr "" #: umake/frameworks/ide.py:131 msgid "Eclipse Luna" msgstr "Eclipse Luna" #: umake/frameworks/ide.py:217 msgid "PyCharm Community Edition" msgstr "PyCharm Community Ausgabe" #: umake/frameworks/ide.py:233 #, fuzzy msgid "PyCharm Educational Edition" msgstr "PyCharm Community Ausgabe" #: umake/frameworks/ide.py:249 #, fuzzy msgid "PyCharm Professional Edition" msgstr "PyCharm Community Ausgabe" #: umake/frameworks/ide.py:265 msgid "IntelliJ IDEA Community Edition" msgstr "IntelliJ IDEA Community Ausgabe" #: umake/frameworks/ide.py:281 msgid "IntelliJ IDEA" msgstr "IntelliJ IDEA" #: umake/frameworks/ide.py:297 msgid "Ruby on Rails IDE" msgstr "" #: umake/frameworks/ide.py:314 msgid "Complex client-side and server-side javascript IDE" msgstr "" #: umake/frameworks/ide.py:331 msgid "PHP and web development IDE" msgstr "" #: umake/frameworks/ide.py:348 msgid "CLion integrated C/C++ IDE" msgstr "" #: umake/frameworks/ide.py:376 msgid "The Arduino Software Distribution" msgstr "" #: umake/frameworks/ide.py:475 msgid "The Arduino Software IDE" msgstr "" #: umake/frameworks/ide.py:478 msgid "Arduino" msgstr "" #: umake/frameworks/ide.py:484 msgid "You need to logout and login again for your installation to work" msgstr "" #: umake/frameworks/ide.py:504 umake/frameworks/ide.py:584 #: umake/frameworks/ide.py:587 msgid "Netbeans IDE" msgstr "" #: umake/frameworks/dart.py:43 msgid "Dartlang Development Environment" msgstr "Dartlang Entwicklungsumgebung" #: umake/frameworks/dart.py:49 #, fuzzy msgid "Dart SDK with editor (not supported upstream anyymore)" msgstr "Dart Software Development Kit mit Editor (Standard)" #: umake/frameworks/dart.py:56 #, fuzzy msgid "Dart SDK (default)" msgstr "Dart Software Development Kit mit Editor (Standard)" #: umake/frameworks/dart.py:97 umake/frameworks/rust.py:134 #: umake/frameworks/scala.py:66 umake/frameworks/go.py:76 #: umake/frameworks/android.py:135 msgid "" "You need to restart your current shell session for your {} installation to " "work properly" msgstr "" #: umake/frameworks/rust.py:43 #, fuzzy msgid "Rust language" msgstr "Go Programmiersprache" #: umake/frameworks/rust.py:56 msgid "The official Rust distribution" msgstr "" #: umake/frameworks/scala.py:40 msgid "The Scala Programming Language" msgstr "" #: umake/frameworks/scala.py:46 #, fuzzy msgid "Scala compiler and interpreter (default)" msgstr "Google Compiler" #: umake/frameworks/go.py:39 msgid "Go language" msgstr "Go Programmiersprache" #: umake/frameworks/go.py:46 msgid "Google compiler (default)" msgstr "Google Compiler" #: umake/frameworks/android.py:42 msgid "Android Development Environment" msgstr "Android Entwicklungsumgebung" #: umake/frameworks/android.py:80 msgid "Android Studio (default)" msgstr "Android Studio" #: umake/frameworks/android.py:100 msgid "Android Studio" msgstr "Android Studio" #: umake/frameworks/android.py:103 msgid "Android Studio developer environment" msgstr "Android Studio Entwicklungsumgebung" #: umake/frameworks/android.py:111 #, fuzzy msgid "Android SDK" msgstr "Android NDK" #: umake/frameworks/android.py:147 msgid "Android NDK" msgstr "Android NDK" #: umake/frameworks/__init__.py:129 msgid "A default framework for category {} was requested where there is none" msgstr "" #: umake/frameworks/__init__.py:240 msgid "You can't install that framework on this machine" msgstr "" #: umake/frameworks/__init__.py:256 msgid "You can't remove {} as it isn't installed" msgstr "{} kann nicht deinstalliert werden, da es nicht installiert ist" #: umake/frameworks/__init__.py:285 msgid "" "If the default framework name isn't provided, destdir should contain a /" msgstr "" "Wenn der Name des standard Frameworks nicht gegeben ist, so sollte das " "Zielverzeichnis ein / enthalten" #: umake/frameworks/__init__.py:288 msgid "Remove framework if installed" msgstr "Entferne, falls installiert, das Framework" #: umake/frameworks/__init__.py:291 msgid "Accept license without prompting" msgstr "" #: umake/frameworks/web.py:45 msgid "Web Developer Environment" msgstr "Web Entwicklerumgebung" #: umake/frameworks/web.py:51 umake/frameworks/web.py:120 msgid "Firefox Developer Edition" msgstr "Firefox Entwicklerausgabe" #: umake/frameworks/web.py:116 #, fuzzy msgid "Choose language: {}" msgstr "Go Programmiersprache" #: umake/frameworks/web.py:123 msgid "Firefox Aurora with Developer tools" msgstr "Firefox Aurora mit Entwicklerwerkzeugen" #: umake/frameworks/web.py:129 msgid "Install in given language without prompting" msgstr "" #: umake/frameworks/web.py:141 umake/frameworks/web.py:226 msgid "Visual Studio focused on modern web and cloud" msgstr "" #: umake/frameworks/web.py:223 msgid "Visual Studio Code" msgstr "" #: umake/frameworks/games.py:42 msgid "Games Development Environment" msgstr "Spiele Entwicklungsumgebung" #: umake/frameworks/games.py:48 msgid "Stencyl game developer IDE" msgstr "" #: umake/frameworks/games.py:85 msgid "Stencyl" msgstr "Stencyl" #: umake/frameworks/games.py:114 msgid "Unity 3D Editor Linux experimental support" msgstr "" #: umake/frameworks/games.py:154 #, fuzzy msgid "Unity3D Editor" msgstr "Dart Editor" #: umake/frameworks/games.py:164 msgid "Twine tool for creating interactive and nonlinear stories" msgstr "" #: umake/frameworks/games.py:200 msgid "Twine" msgstr "" #: umake/interactions/__init__.py:73 msgid "No suitable answer provided" msgstr "Keine passende Antwort verfügbar" #: umake/interactions/__init__.py:75 umake/interactions/__init__.py:83 msgid "Your entry '{}' isn't an acceptable choice. choices are: {}" msgstr "Ihre Eingabe '{}' ist nicht erlaubt. Mögliche Eingaben sind: {}" #: umake/interactions/__init__.py:80 msgid "Your entry '{}' isn't an acceptable choice. choices are: {} and {}" msgstr "Ihre Eingabe '{}' ist nicht erlaubt. Mögliche Eingaben sind {} oder {}" #: umake/interactions/__init__.py:100 msgid " ({})" msgstr " ({})" #: umake/interactions/__init__.py:104 msgid "" "{}\n" "[{}] " msgstr "" "{}\n" "[{}] " #: umake/interactions/__init__.py:107 msgid "{} [{}] " msgstr "{} [{}] " #: umake/interactions/__init__.py:115 msgid "I Accept" msgstr "Ich akzeptiere" #: umake/interactions/__init__.py:115 msgid "a" msgstr "a" #: umake/interactions/__init__.py:116 msgid "I don't accept" msgstr "Ich akzeptiere nicht" #: umake/interactions/__init__.py:116 umake/interactions/__init__.py:149 msgid "N" msgstr "N" #: umake/interactions/__init__.py:125 umake/interactions/__init__.py:126 msgid "{} ({})" msgstr "{} ({})" #: umake/interactions/__init__.py:129 msgid "[{}] " msgstr "[{}] " #: umake/interactions/__init__.py:148 msgid "Yes" msgstr "Ja" #: umake/interactions/__init__.py:148 msgid "y" msgstr "j" #: umake/interactions/__init__.py:149 msgid "No" msgstr "Nein" #~ msgid "Stencyl Game developer environment" #~ msgstr "Stencyl Spiele Entwicklerumgebung" #~ msgid "Dart Editor for the dart language" #~ msgstr "Dart Editor für die dart Programmiersprache" ubuntu-make-16.11.1ubuntu1/requirements.txt0000664000000000000000000000030013013560574015613 0ustar # runtime requirements -e bzr+lp:python-apt/@0.9.3.5#egg=apt argcomplete beautifulsoup4 progressbar pyyaml requests pyxdg python-gnupg # test tools nose nose-cov nose-json pep8 pexpect>=4.0 ubuntu-make-16.11.1ubuntu1/tests/0000775000000000000000000000000013013560574013500 5ustar ubuntu-make-16.11.1ubuntu1/tests/__init__.py0000664000000000000000000000277413013560574015623 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Ensure we keep a sane formatting syntax""" import os import pep8 from .tools import get_root_dir import umake from unittest import TestCase class CodeCheck(TestCase): def test_pep8(self): """Proceed a pep8 checking Note that we have a .pep8 config file for maximum line length tweak and excluding the virtualenv dir.""" pep8style = pep8.StyleGuide(config_file=os.path.join(get_root_dir(), '.pep8')) # we want to use either local or system umake, but always local tests files umake_dir = os.path.dirname(umake.__file__) results = pep8style.check_files([umake_dir, os.path.join(get_root_dir(), "tests"), os.path.join(get_root_dir(), "bin")]) self.assertEqual(results.get_statistics(), []) ubuntu-make-16.11.1ubuntu1/tests/large/0000775000000000000000000000000013013560574014572 5ustar ubuntu-make-16.11.1ubuntu1/tests/large/__init__.py0000664000000000000000000002310513013560574016704 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Basic large tests class""" from contextlib import suppress from nose.tools import nottest import os import pexpect import shutil import signal import stat import subprocess from time import sleep from umake.tools import get_icon_path, get_launcher_path, launcher_exists_and_is_pinned, remove_framework_envs_from_user from ..tools import LoggedTestCase, get_path_from_desktop_file, is_in_group, INSTALL_DIR, swap_file_and_restore, \ spawn_process from umake.settings import DEFAULT_BINARY_LINK_PATH class LargeFrameworkTests(LoggedTestCase): """Large framework base utilities""" in_container = False def setUp(self): super().setUp() self.installed_path = "" self.framework_name_for_profile = "" self.conf_path = os.path.expanduser("~/.config/umake") self.install_base_path = os.path.expanduser("~/{}".format(INSTALL_DIR)) self.binary_dir = DEFAULT_BINARY_LINK_PATH self.desktop_filename = "" self.child = None self.additional_dirs = [] self.original_env = os.environ.copy() # we want to standardize on bash environment for running large tests os.environ["SHELL"] = "/bin/bash" def tearDown(self): # don't remove on machine paths if running within a container if not self.in_container: with suppress(FileNotFoundError): shutil.rmtree(self.installed_path) # TODO: need to be finer grain in the future with suppress(FileNotFoundError): os.remove(self.conf_path) if self.desktop_filename: with suppress(FileNotFoundError): os.remove(get_launcher_path(self.desktop_filename)) os.remove(self.exec_link) remove_framework_envs_from_user(self.framework_name_for_profile) for dir in self.additional_dirs: with suppress(OSError): shutil.rmtree(dir) # restore original environment. Do not use the dict copy which erases the object and doesn't have the magical # _Environ which setenv() for subprocess os.environ.clear() os.environ.update(self.original_env) super().tearDown() def _pid_for(self, process_grep): """Return pid matching the process_grep elements""" for pid in os.listdir('/proc'): if not pid.isdigit(): continue # ignore processes that are closed in between with suppress(IOError): cmdline = open(os.path.join('/proc', pid, 'cmdline'), 'r').read() for process_elem in process_grep: if process_elem not in cmdline: break # we found it else: return int(pid) raise BaseException("The process that we can find with {} isn't started".format(process_grep)) def check_and_kill_process(self, process_grep, wait_before=0, send_sigkill=False): """Check a process matching process_grep exists and kill it""" sleep(wait_before) pid = self._pid_for(process_grep) if send_sigkill: os.kill(pid, signal.SIGKILL) else: os.kill(pid, signal.SIGTERM) @property def exec_link(self): return os.path.join(self.binary_dir, self.desktop_filename.split('.')[0]) @property def exec_path(self): return self._get_path_from_desktop_file("Exec") def _get_path_from_desktop_file(self, key, abspath_transform=None): """get the path referred as key in the desktop filename exists""" path = get_path_from_desktop_file(self.desktop_filename, key) if not path.startswith("/") and abspath_transform: path = abspath_transform(path) return path def assert_exec_exists(self): """Assert that the exec path exists""" self.assertTrue(self.path_exists(self.exec_path)) def assert_icon_exists(self): """Assert that the icon path exists""" self.assertTrue(self.path_exists(self._get_path_from_desktop_file('Icon', get_icon_path))) def assert_exec_link_exists(self): """Assert that the link to the binary exists""" self.assertTrue(self.is_in_path(self.exec_link)) def assert_for_warn(self, content, expect_warn=False): """assert if there is any warn""" if not expect_warn: # We need to remove the first expected message, which is "Logging level set to " # (can be WARNING or ERROR) content = content.replace("Logging level set to WARNING", "").replace("Logging level set to ERROR", "") self.assertNotIn("WARNING", content) self.assertNotIn("ERROR", content) else: for warn_tag in ("WARNING", "ERROR"): if warn_tag in content: break else: # nothing found: raise BaseException("We didn't find an expected WARNING or ERROR in {}".format(content)) def expect_and_no_warn(self, expect_query, timeout=-1, expect_warn=False): """run the expect query and check that there is no warning or error It doesn't fail on the given timeout if stdout is progressing""" output = "" continue_expect = True while continue_expect: try: self.child.expect(expect_query, timeout=timeout) continue_expect = False except pexpect.TIMEOUT: # stalled during timeout period if output == self.child.before: print(self.child.before) raise output = self.child.before # print the whole process output before getting the pexpect exception except: print(self.child.before) raise self.assert_for_warn(self.child.before, expect_warn) def wait_and_no_warn(self, expect_warn=False): """run wait and check that there is no warning or error""" self.expect_and_no_warn(pexpect.EOF, expect_warn=expect_warn) def accept_default_and_wait(self, expect_warn=False): """accept default and wait for exiting""" self.child.sendline("") self.wait_and_no_warn(expect_warn) def close_and_check_status(self, exit_status=0): """exit child process and check its exit status""" self.child.close() self.assertEqual(exit_status, self.child.exitstatus) def wait_and_close(self, expect_warn=False, exit_status=0): """wait for exiting and check exit status""" self.wait_and_no_warn(expect_warn) self.close_and_check_status(exit_status) def command(self, commands_to_run): """passthrough, return args""" return commands_to_run def command_as_list(self, commands_input): """passthrough, return args""" return commands_input def get_launcher_path(self, desktop_filename): """passthrough getting the launcher path from umake tools""" return get_launcher_path(desktop_filename) def launcher_exists_and_is_pinned(self, desktop_filename): """passthrough to in process method""" return launcher_exists_and_is_pinned(desktop_filename) def path_exists(self, path): """passthrough to os.path.exists""" return os.path.exists(path) def remove_path(self, path): """Remove targeted path""" try: os.remove(path) except OSError: shutil.rmtree(path) def is_in_path(self, filename): """check that we have a directory in path""" return_code = subprocess.call(["bash", "-l", "which", filename], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if return_code == 0: return True elif return_code == 1: return False raise BaseException("Unknown return code for looking if {} is in path".format(filename)) def is_in_group(self, group): """return if current user is in a group""" return is_in_group(group) def get_file_perms(self, path): """return unix file perms string for path""" return stat.filemode(os.stat(path).st_mode) def create_file(self, path, content): """passthrough to create a file on the disk""" open(path, 'w').write(content) @nottest def bad_download_page_test(self, command, content_file_path): """Helper for running a test to confirm failure on a significantly changed download page.""" with swap_file_and_restore(content_file_path): with open(content_file_path, "w") as newfile: newfile.write("foo") self.child = spawn_process(command) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.wait_and_close(expect_warn=True, exit_status=1) ubuntu-make-16.11.1ubuntu1/tests/large/test_go.py0000664000000000000000000000516413013560574016616 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # Tin Tvrtković # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Go category""" import subprocess import os import tempfile from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process class GoTests(LargeFrameworkTests): """The default Go google compiler.""" TIMEOUT_INSTALL_PROGRESS = 300 EXAMPLE_PROJECT = """package main import "fmt" func main() { fmt.Printf("hello, world") }""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "go", "go-lang") self.framework_name_for_profile = "Go Lang" @property def exec_path(self): return os.path.join(self.installed_path, "bin", "go") def test_default_go_install(self): """Install Go from scratch test case""" if not self.in_container: self.example_prog_dir = tempfile.mkdtemp() self.additional_dirs.append(self.example_prog_dir) example_file = os.path.join(self.example_prog_dir, "hello.go") open(example_file, "w").write(self.EXAMPLE_PROJECT) compile_command = ["bash", "-l", "-c", "go run {}".format(example_file)] else: # our mock expects getting that path compile_command = ["bash", "-l", "go run /tmp/hello.go"] self.child = spawn_process(self.command('{} go'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # compile a small project output = subprocess.check_output(self.command_as_list(compile_command)).decode()\ .replace('\r', '').replace('\n', '') self.assertEqual(output, "hello, world") ubuntu-make-16.11.1ubuntu1/tests/large/test_baseinstaller.py0000664000000000000000000006761613013560574021053 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for large base installer framework""" from . import LargeFrameworkTests import os import pexpect import platform import shutil import subprocess import tempfile from ..tools import UMAKE, spawn_process, get_data_dir, swap_file_and_restore from ..tools.local_server import LocalHttp class BaseInstallerTests(LargeFrameworkTests): """This will test the base installer framework via a fake one""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 1 TIMEOUT_STOP = 1 server = None TEST_URL_FAKE_DATA = "http://localhost:8765/base-framework-fake64.tgz" TEST_CHECKSUM_FAKE_DATA = "4a582c6e35700f00332783b0b83783f73499aa60" JAVAEXEC = "java-fake64" @classmethod def setUpClass(cls): super().setUpClass() cls.proxy_env = {"http_proxy": None, "https_proxy": None} for key in cls.proxy_env: cls.proxy_env[key] = os.environ.pop(key, None) cls.download_page_file_path = os.path.join(get_data_dir(), "server-content", "localhost", "index.html") if not cls.in_container: server_dir = os.path.join(get_data_dir(), "server-content", "localhost") cls.server = LocalHttp(server_dir, port=8765) framework_dir = os.path.expanduser(os.path.join('~', '.umake', 'frameworks')) cls.testframework = (os.path.join(framework_dir, 'baseinstallerfake.py')) os.makedirs(framework_dir, exist_ok=True) shutil.copy(os.path.join(get_data_dir(), "testframeworks", "baseinstallerfake.py"), cls.testframework) if platform.machine() != "x86_64": cls.TEST_URL_FAKE_DATA = "http://localhost:8765/base-framework-fake32.tgz" cls.TEST_CHECKSUM_FAKE_DATA = "4f64664ebe496cc6d54f417f25a1707f156d74d2" cls.JAVAEXEC = "java-fake32" @classmethod def tearDownClass(cls): super().tearDownClass() for key, value in cls.proxy_env.items(): if value: os.environ[key] = value if not cls.in_container: os.remove(cls.testframework) cls.server.stop() def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "base", "base-framework") self.desktop_filename = "base-framework.desktop" self.required_files_path = ["base"] @property def arch_option(self): """we return the expected arch call on command line""" return platform.machine() def test_default_install(self): """Install base installer from scratch test case""" self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.JAVAEXEC, self.installed_path], wait_before=self.TIMEOUT_START) self.assertEqual(proc.wait(self.TIMEOUT_STOP), 143) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Base Framework is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() def test_no_license_accept(self): """We don't accept the license (default)""" self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.accept_default_and_wait() self.close_and_check_status() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_doesnt_accept_wrong_path(self): """We don't accept a wrong path""" self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline(chr(127) * 100) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline(chr(127) * 100 + "/") self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path), expect_warn=True) self.child.sendcontrol('C') self.wait_and_no_warn() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_reinstall(self): """Reinstall once installed""" for loop in ("install", "reinstall"): self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) if loop == "reinstall": # we only have one question, not the one about existing dir. self.expect_and_no_warn("Base Framework is already installed.*\[.*\] ") self.child.sendline("y") self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.JAVAEXEC, self.installed_path], wait_before=self.TIMEOUT_START) def test_reinstall_other_path(self): """Reinstall Base Framework on another path once installed should remove the first version""" original_install_path = self.installed_path for loop in ("install", "reinstall"): if loop == "reinstall": self.installed_path = "/tmp/foo" self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("Base Framework is already installed.*\[.*\] ") self.child.sendline("y") else: self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() # ensure that version first isn't installed anymore self.assertFalse(self.path_exists(original_install_path)) def test_reinstall_other_non_empty_path(self): """Reinstall Base Framework on another path (non empty) once installed should remove the first version""" original_install_path = self.installed_path if not self.in_container: self.reinstalled_path = tempfile.mkdtemp() else: # we still give a path for the container self.reinstalled_path = os.path.join(tempfile.gettempdir(), "tmptests") self.create_file(os.path.join(self.reinstalled_path, "bar"), "foo") for loop in ("install", "reinstall"): if loop == "reinstall": self.installed_path = self.reinstalled_path self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("Base Framework is already installed.*\[.*\] ") self.child.sendline("y") self.expect_and_no_warn("{} isn't an empty directory.*there\? \[.*\] ".format(self.installed_path)) self.child.sendline("y") else: self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() # ensure that version first isn't installed anymore self.assertFalse(self.path_exists(original_install_path)) def test_reinstall_previous_install_removed(self): """Detect that removing Base Framework content, but still having a launcher, doesn't trigger a reinstall question""" for loop in ("install", "reinstall"): if loop == "reinstall": # remove code (but not laucher) self.remove_path(self.installed_path) self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() def test_reinstall_previous_launcher_removed(self): """Detect that removing Base Framework launcher, but still having the code, doesn't trigger a reinstall question. However, we do have a dir isn't empty one.""" for loop in ("install", "reinstall"): if loop == "reinstall": # remove launcher, but not code self.remove_path(self.get_launcher_path(self.desktop_filename)) self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") if loop == "reinstall": self.expect_and_no_warn("{} isn't an empty directory.*there\? \[.*\] ".format(self.installed_path)) self.child.sendline("y") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() def test_xdg_data_install_path(self): """Install in path specified by XDG_DATA_HOME""" xdg_data_path = "/tmp/foo" self.installed_path = "{}/umake/base/base-framework".format(xdg_data_path) cmd = "XDG_DATA_HOME={} {} base base-framework".format(xdg_data_path, UMAKE) if not self.in_container: cmd = 'bash -c "{}"'.format(cmd) self.child = spawn_process(self.command(cmd)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") self.accept_default_and_wait() self.close_and_check_status() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_custom_install_path(self): """We install Base Framework in a custom path""" # We skip the existing directory prompt self.installed_path = "/tmp/foo" self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license as the first question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.JAVAEXEC, self.installed_path], wait_before=self.TIMEOUT_START) self.assertEqual(proc.wait(self.TIMEOUT_STOP), 143) def test_start_install_on_empty_dir(self): """We try to install on an existing empty dir""" if not self.in_container: self.installed_path = tempfile.mkdtemp() else: # we still give a path for the container self.installed_path = os.path.join(tempfile.gettempdir(), "tmptests") self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license as the first question self.accept_default_and_wait() self.close_and_check_status() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_start_install_on_existing_dir_refuse(self): """We prompt if we try to install on an existing directory which isn't empty. Refusing doesn't install""" if not self.in_container: self.installed_path = tempfile.mkdtemp() else: # we still give a path for the container self.installed_path = os.path.join(tempfile.gettempdir(), "tmptests") self.create_file(os.path.join(self.installed_path, "bar"), "foo") self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("{} isn't an empty directory.*there\? \[.*\] ".format(self.installed_path)) self.accept_default_and_wait() self.close_and_check_status() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_start_install_on_existing_dir_accept(self): """We prompt if we try to install on an existing directory which isn't empty. Accepting install""" if not self.in_container: self.installed_path = tempfile.mkdtemp() else: # we still give a path for the container self.installed_path = os.path.join(tempfile.gettempdir(), "tmptests") self.create_file(os.path.join(self.installed_path, "bar"), "foo") self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("{} isn't an empty directory.*there\? \[.*\] ".format(self.installed_path)) self.child.sendline("y") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.JAVAEXEC, self.installed_path], wait_before=self.TIMEOUT_START) self.assertEqual(proc.wait(self.TIMEOUT_STOP), 143) def test_is_default_framework(self): """Base Framework is chosen as the default framework""" self.child = spawn_process(self.command('{} base'.format(UMAKE))) # we ensure it thanks to installed_path being the base framework one self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendcontrol('C') self.wait_and_no_warn() def test_is_default_framework_with_options(self): """Base Framework options are sucked in as the default framework""" self.child = spawn_process(self.command('{} base /tmp/foo'.format(UMAKE))) self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license as the first question self.accept_default_and_wait() self.close_and_check_status() def test_not_default_framework_with_path_without_path_separator(self): """Base Framework isn't selected for default framework with path without separator""" self.child = spawn_process(self.command('{} base foo'.format(UMAKE))) self.expect_and_no_warn("error: argument framework: invalid choice") self.accept_default_and_wait() self.close_and_check_status(exit_status=2) def test_is_default_framework_with_user_path(self): """Base Framework isn't selected for default framework with path without separator""" self.installed_path = "/tmp/foo" self.child = spawn_process(self.command('{} base {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license as the first question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.JAVAEXEC, self.installed_path], wait_before=self.TIMEOUT_START) self.assertEqual(proc.wait(self.TIMEOUT_STOP), 143) def test_removal(self): """Remove Base Framework with default path""" self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertTrue(self.path_exists(self.installed_path)) # now, remove it self.child = spawn_process(self.command('{} base base-framework --remove'.format(UMAKE))) self.wait_and_close() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.path_exists(self.installed_path)) self.assertFalse(self.path_exists(self.exec_link)) def test_removal_non_default_path(self): """Remove Base Framework with non default path""" self.installed_path = "/tmp/foo" self.child = spawn_process(self.command('{} base base-framework {}'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertTrue(self.path_exists(self.installed_path)) # now, remove it self.child = spawn_process(self.command('{} base base-framework --remove'.format(UMAKE))) self.wait_and_close() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.path_exists(self.installed_path)) def test_removal_global_option(self): """Remove Base Framework via global option (before category) should delete it""" self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[.*\] ") self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertTrue(self.path_exists(self.installed_path)) # now, remove it self.child = spawn_process(self.command('{} --remove base base-framework'.format(UMAKE))) self.wait_and_close() self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.path_exists(self.installed_path)) def test_automated_install(self): """Install Base Framework automatically with no interactive options""" self.child = spawn_process(self.command('{} base base-framework {} --accept-license'.format(UMAKE, self.installed_path))) self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() def test_try_removing_uninstalled_framework(self): """Trying to remove an uninstalled framework will fail""" self.child = spawn_process(self.command('{} base base-framework --remove'.format(UMAKE))) self.wait_and_close(expect_warn=True, exit_status=1) # additional test with fake md5sum def test_install_with_wrong_md5sum(self): """Install requires a md5sum, and a wrong one is rejected""" with swap_file_and_restore(self.download_page_file_path) as content: with open(self.download_page_file_path, "w") as newfile: newfile.write(content.replace(self.TEST_CHECKSUM_FAKE_DATA, "c8362a0c2ffc07b1b19c4b9001c8532de5a4b8c3")) self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn([pexpect.EOF, "Corrupted download? Aborting."], timeout=self.TIMEOUT_INSTALL_PROGRESS, expect_warn=True) self.wait_and_close(exit_status=1) # we have nothing installed self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_install_with_no_license_in_download_page(self): """Installing should fail if not even license i dowload page""" umake_command = self.command("{} base base-framework".format(UMAKE)) self.bad_download_page_test(umake_command, self.download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_install_with_no_download_links(self): """Installing should fail if no valid download links are found""" with swap_file_and_restore(self.download_page_file_path) as content: with open(self.download_page_file_path, "w") as newfile: newfile.write(content.replace('id="linux-bundle', "")) self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn([pexpect.EOF], timeout=self.TIMEOUT_INSTALL_PROGRESS, expect_warn=True) self.wait_and_close(exit_status=1) # we have nothing installed self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_install_with_404(self): """Installing should fail with a 404 download asset reported correctly""" with swap_file_and_restore(self.download_page_file_path) as content: with open(self.download_page_file_path, "w") as newfile: newfile.write(content.replace(self.TEST_URL_FAKE_DATA, "https://localhost:8765/android-studio-unexisting.tgz")) self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn([pexpect.EOF, "ERROR: 404 Client Error: File not found"], timeout=self.TIMEOUT_INSTALL_PROGRESS, expect_warn=True) self.wait_and_close(exit_status=1) # we have nothing installed self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def test_download_page_404(self): """Download page changed address or is just 404 should be reported correctly""" with swap_file_and_restore(self.download_page_file_path): os.remove(self.download_page_file_path) self.child = spawn_process(self.command('{} base base-framework'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn([pexpect.EOF, "ERROR: 404 Client Error: File not found"], timeout=self.TIMEOUT_INSTALL_PROGRESS, expect_warn=True) self.wait_and_close(exit_status=1) # we have nothing installed self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) ubuntu-make-16.11.1ubuntu1/tests/large/test_kotlin.py0000664000000000000000000000507413013560574017511 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2016 Canonical # # Authors: # Omer Sheikh # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Kotlin category""" import subprocess import os import tempfile from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process class KotlinTests(LargeFrameworkTests): """The default Kotlin compiler.""" TIMEOUT_INSTALL_PROGRESS = 300 EXAMPLE_PROJECT = """println("Hello, world!")""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "kotlin", "kotlin-lang") self.framework_name_for_profile = "Kotlin Lang" @property def exec_path(self): return os.path.join(self.installed_path, "bin", "kotlinc") def test_default_kotlin_install(self): """Install Kotlin from scratch test case""" if not self.in_container: self.example_prog_dir = tempfile.mkdtemp() self.additional_dirs.append(self.example_prog_dir) example_file = os.path.join(self.example_prog_dir, "hello.kts") open(example_file, "w").write(self.EXAMPLE_PROJECT) compile_command = ["bash", "-l", "-c", "kotlinc -script {}".format(example_file)] else: # our mock expects getting that path compile_command = ["bash", "-l", "kotlinc -script /tmp/hello.kts"] self.child = spawn_process(self.command('{} kotlin'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # compile a small project output = subprocess.check_output(self.command_as_list(compile_command)).decode()\ .replace('\r', '').replace('\n', '') self.assertEqual(output, "Hello, world!") ubuntu-make-16.11.1ubuntu1/tests/large/test_web.py0000664000000000000000000001544513013560574016771 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Web category""" import logging import platform import subprocess import os from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process logger = logging.getLogger(__name__) class FirefoxDevTests(LargeFrameworkTests): """Tests for Firefox Developer Edition""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "web", "firefox-dev") self.desktop_filename = "firefox-developer.desktop" @property def arch_option(self): """we return the expected arch call on command line""" return platform.machine() def verify_install(self, installed_language): # we have an installed launcher, added to the launcher, a dictionary file and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertTrue(self.language_file_exists(installed_language)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["firefox", self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} web firefox-dev'.format(UMAKE))) self.expect_and_no_warn("Firefox Dev is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() def test_default_install(self): """Install firefox dev from scratch test case""" install_language = "en-US" self.child = spawn_process(self.command('{} web firefox-dev'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Choose language:") self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.verify_install(install_language) def test_arg_language_select_install(self): """Install firefox dev with language selected by --lang""" install_language = "bg" self.child = spawn_process(self.command('{} web firefox-dev --lang={}'.format(UMAKE, install_language))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.verify_install(install_language) def test_interactive_language_select_install(self): """Install firefox dev with language selected interactively""" install_language = "bg" self.child = spawn_process(self.command('{} web firefox-dev'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Choose language:") self.child.sendline(install_language) self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.verify_install(install_language) def test_unavailable_language_select_install(self): """Installing Firefox-dev in unavailable language should be rejected""" install_language = "ABCdwXYZ" self.child = spawn_process(self.command('{} web firefox-dev --lang={}'.format(UMAKE, install_language))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.wait_and_close(expect_warn=True, exit_status=1) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) def language_file_exists(self, language): return self.path_exists(os.path.join(self.installed_path, "dictionaries", "{}.aff".format(language))) class VisualStudioCodeTest(LargeFrameworkTests): """Tests for Visual Studio Code""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "web", "visual-studio-code") self.desktop_filename = "visual-studio-code.desktop" def test_default_install(self): """Install visual studio from scratch test case""" self.child = spawn_process(self.command('{} web visual-studio-code'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path), expect_warn=True) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.exec_path, self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} web visual-studio-code'.format(UMAKE))) self.expect_and_no_warn("Visual Studio Code is already installed.*\[.*\] ", expect_warn=True) self.child.sendline() self.wait_and_close() ubuntu-make-16.11.1ubuntu1/tests/large/test_nodejs.py0000664000000000000000000000722413013560574017472 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Nodejs category""" import subprocess import os import tempfile from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process class NodejsTests(LargeFrameworkTests): """Nodejs stable.""" TIMEOUT_INSTALL_PROGRESS = 300 EXAMPLE_PROJECT = """console.log("Hello World");""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "nodejs", "nodejs-lang") self.framework_name_for_profile = "Nodejs Lang" @property def exec_path(self): return os.path.join(self.installed_path, "bin", "node") def test_default_nodejs_install(self): """Install Nodejs from scratch test case""" if not self.in_container: self.example_prog_dir = tempfile.mkdtemp() self.additional_dirs.append(self.example_prog_dir) example_file = os.path.join(self.example_prog_dir, "hello.js") open(example_file, "w").write(self.EXAMPLE_PROJECT) compile_command = ["bash", "-l", "-c", "node {}".format(example_file)] npm_command = ["bash", "-l", "-c", "npm config get prefix"] else: # our mock expects getting that path compile_command = ["bash", "-l", "node /tmp/hello.js"] npm_command = ["bash", "-l", "npm config get prefix"] self.child = spawn_process(self.command('{} nodejs'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) npm_path = os.path.join(self.installed_path, "bin", "npm") self.assertTrue(self.path_exists(npm_path)) self.assertTrue(self.is_in_path(npm_path)) # compile a small project output = subprocess.check_output(self.command_as_list(compile_command)).decode()\ .replace('\r', '').replace('\n', '') # set npm prefix npm_output = subprocess.check_output(self.command_as_list(npm_command)).decode()\ .replace('\r', '').replace('\n', '') self.assertEqual(output, "Hello World") self.assertEqual(npm_output, "{}/.npm_modules".format(os.path.join("/", self.installed_path.split('/')[1], self.installed_path.split('/')[2]))) def test_lts_select_install(self): """Install nodejs lts""" self.child = spawn_process(self.command('{} nodejs --lts').format(UMAKE)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() ubuntu-make-16.11.1ubuntu1/tests/large/test_dart.py0000664000000000000000000000411313013560574017134 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Dart category""" import logging import os from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process logger = logging.getLogger(__name__) class DartEditorTests(LargeFrameworkTests): """Tests for Dart Editor with SDK""" TIMEOUT_INSTALL_PROGRESS = 120 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "dart", "dart-sdk") @property def exec_path(self): return os.path.join(self.installed_path, "bin", "dart") def test_default_dart_install(self): """Install dart editor from scratch test case""" self.child = spawn_process(self.command('{} dart'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} dart'.format(UMAKE))) self.expect_and_no_warn("Dart SDK is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() ubuntu-make-16.11.1ubuntu1/tests/large/test_general.py0000664000000000000000000000261513013560574017624 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """General frameworks tests""" from . import LargeFrameworkTests import subprocess from ..tools import UMAKE class GeneralTests(LargeFrameworkTests): """This will test the General frameworks functionality""" def test_run_category_without_default_framework(self): """Trying to run a category without a default framework exits in error""" exception_raised = False try: subprocess.check_output(self.command_as_list([UMAKE, 'ide']), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: self.assertIn("ERROR:", e.output.decode("utf-8")) exception_raised = True self.assertTrue(exception_raised) ubuntu-make-16.11.1ubuntu1/tests/large/test_games.py0000664000000000000000000001740113013560574017302 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for android""" from . import LargeFrameworkTests import os import platform import subprocess from ..tools import UMAKE, spawn_process class StencylTests(LargeFrameworkTests): """This will test the Stencyl installation""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "games", "stencyl") self.desktop_filename = "stencyl.desktop" def test_default_stencyl_install(self): """Install stencyl from scratch test case""" self.child = spawn_process(self.command('{} games stencyl'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine use_cwd = self.installed_path if self.in_container: use_cwd = None proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=use_cwd) self.check_and_kill_process(["./runtimes/jre-linux/bin/java"], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} games stencyl'.format(UMAKE))) self.expect_and_no_warn("Stencyl is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class Unity3DTests(LargeFrameworkTests): """This will test the Unity 3D editor installation""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "games", "unity3d") self.desktop_filename = "unity3d-editor.desktop" def test_default_unity3D_install(self): """Install unity3D editor from scratch test case""" # only an amd64 test if platform.machine() != "x86_64": return self.child = spawn_process(self.command('{} games unity3d'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # ensure setuid self.assertEqual(self.get_file_perms(os.path.join(self.installed_path, "Editor", "chrome-sandbox")), '-rwsr-xr-x') # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.exec_path], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} games unity3d'.format(UMAKE))) self.expect_and_no_warn("Unity3d is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class TwineTests(LargeFrameworkTests): """This will test the Twine installation""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "games", "twine") self.desktop_filename = "twine.desktop" def test_default_twine_install(self): """Install twine editor from scratch test case""" self.child = spawn_process(self.command('{} games twine'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.exec_path], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} games twine'.format(UMAKE))) self.expect_and_no_warn("Twine is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class SuperpowersTests(LargeFrameworkTests): """This will test the Superpowers installation""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "games", "superpowers") self.desktop_filename = "superpowers.desktop" self.command_args = '{} games superpowers'.format(UMAKE) def test_default_superpowers_install(self): """Install Superpowers editor from scratch test case""" self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.exec_path], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Superpowers is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() ubuntu-make-16.11.1ubuntu1/tests/large/test_scala.py0000664000000000000000000000524613013560574017275 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # Tin Tvrtković # Igor Vuk # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Scala category""" import subprocess import os import tempfile from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process class ScalaTests(LargeFrameworkTests): """The default Scala compiler.""" TIMEOUT_INSTALL_PROGRESS = 300 EXAMPLE_PROJECT = """object HelloWorld { def main(args: Array[String]) { println("hello, world") } }""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "scala", "scala-lang") self.framework_name_for_profile = "Scala Lang" @property def exec_path(self): return os.path.join(self.installed_path, "bin", "scala") def test_default_scala_install(self): """Install Scala from scratch test case""" if not self.in_container: self.example_prog_dir = tempfile.mkdtemp() self.additional_dirs.append(self.example_prog_dir) example_file = os.path.join(self.example_prog_dir, "hello.scala") open(example_file, "w").write(self.EXAMPLE_PROJECT) compile_command = ["bash", "-l", "-c", "scala {}".format(example_file)] else: # our mock expects getting that path compile_command = ["bash", "-l", "scala /tmp/hello.scala"] self.child = spawn_process(self.command('{} scala'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # compile a small project output = subprocess.check_output(self.command_as_list(compile_command)).decode()\ .replace('\r', '').replace('\n', '') self.assertEqual(output, "hello, world") ubuntu-make-16.11.1ubuntu1/tests/large/test_rust.py0000664000000000000000000000715613013560574017211 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014-2015 Canonical # # Authors: # Didier Roche # Tin Tvrtković # Jared Ravetch # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Rust category""" import subprocess import os import tempfile from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process class RustTests(LargeFrameworkTests): """The official Rust distribution""" TIMEOUT_INSTALL_PROGRESS = 300 EXAMPLE_PROJECT = """fn main() {println!("hello, world");}""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "rust", "rust-lang") self.framework_name_for_profile = "Rust" @property def exec_path(self): return os.path.join(self.installed_path, "rustc", "bin", "rustc") def test_default_rust_install(self): """Install Rust from scratch test case""" if not self.in_container: self.example_prog_dir = tempfile.mkdtemp() self.additional_dirs.append(self.example_prog_dir) example_file = os.path.join(self.example_prog_dir, "hello.rs") open(example_file, "w").write(self.EXAMPLE_PROJECT) # rust compile in pwd by default, do not pollute ubuntu make source code compile_command = ["bash", "-l", "-c", "rustc --out-dir {} {}".format(self.example_prog_dir, example_file)] else: # our mock expects getting that path self.example_prog_dir = "/tmp" example_file = os.path.join(self.example_prog_dir, "hello.rs") # rust compile in pwd by default, do not pollute ubuntu make source code compile_command = ["bash", "-l", "rustc --out-dir {} {}".format(self.example_prog_dir, example_file)] resulting_binary = os.path.join(self.example_prog_dir, "hello") self.child = spawn_process(self.command('{} rust'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) self.assertTrue(self.is_in_path(os.path.join(self.installed_path, "cargo", "bin", "cargo"))) cmd_list = ["echo $LD_LIBRARY_PATH"] if not self.in_container: relogging_command = ["bash", "-l", "-c"] relogging_command.extend(cmd_list) cmd_list = relogging_command self.assertIn(os.path.join(self.installed_path, "rustc", "lib"), subprocess.check_output(self.command_as_list(cmd_list)).decode("utf-8").strip().split(":")) # compile a small project subprocess.check_call(self.command_as_list(compile_command)) # run the compiled result output = subprocess.check_output(self.command_as_list(resulting_binary)).decode()\ .replace('\r', '').replace('\n', '') self.assertEqual(output, "hello, world") ubuntu-make-16.11.1ubuntu1/tests/large/test_swift.py0000664000000000000000000000516713013560574017350 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the Swift category""" import subprocess import os import tempfile from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process class SwiftTests(LargeFrameworkTests): """The default Swift compiler.""" TIMEOUT_INSTALL_PROGRESS = 300 EXAMPLE_PROJECT = """print("Hello, world!") """ def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "swift", "swift-lang") self.framework_name_for_profile = "Swift Lang" @property def exec_path(self): return os.path.join(self.installed_path, "usr", "bin", "swift") def test_default_swift_install(self): """Install Swift from scratch test case""" if not self.in_container: self.example_prog_dir = tempfile.mkdtemp() self.additional_dirs.append(self.example_prog_dir) example_file = os.path.join(self.example_prog_dir, "main.swift") open(example_file, "w").write(self.EXAMPLE_PROJECT) compile_command = ["bash", "-l", "-c", "swift {}".format(example_file)] else: # our mock expects getting that command parameter self.example_prog_dir = "/tmp" compile_command = ["bash", "-l", "swift /tmp/main.swift"] self.child = spawn_process(self.command('{} swift'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # run the compiled result output = subprocess.check_output(self.command_as_list(compile_command)).decode()\ .replace('\r', '').replace('\n', '') self.assertEqual(output, "Hello, world!") ubuntu-make-16.11.1ubuntu1/tests/large/test_basics_cli.py0000664000000000000000000001257713013560574020312 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for basic CLI commands""" from contextlib import suppress import os import subprocess from . import LargeFrameworkTests from ..tools import LoggedTestCase, UMAKE, get_root_dir class BasicCLI(LargeFrameworkTests): """This will test the basic cli command class""" @classmethod def setUpClass(cls): super().setUpClass() cls.log_cfg = None with suppress(KeyError): cls.log_cfg = os.environ.pop("LOG_CFG") @classmethod def tearDownClass(cls): super().tearDownClass() if (cls.log_cfg): os.environ["LOG_CFG"] = cls.log_cfg def command_as_list(self, commands_input): """passthrough, return args""" return commands_input def return_without_first_output(self, stdout): """We return ignoring the first line which is INFO: set logging level to""" return "\n".join(stdout.split('\n')[1:]) def test_global_help(self): """We display a global help message""" result = subprocess.check_output(self.command_as_list([UMAKE, '--help'])) self.assertNotEqual(result, "") def test_setup_info_logging(self): """We display info logs""" result = subprocess.check_output(self.command_as_list([UMAKE, '-v', '--help']), stderr=subprocess.STDOUT) self.assertIn("INFO:", self.return_without_first_output(result.decode("utf-8"))) def test_setup_debug_logging(self): """We display debug logs""" result = subprocess.check_output(self.command_as_list([UMAKE, '-vv', '--help']), stderr=subprocess.STDOUT) self.assertIn("DEBUG:", self.return_without_first_output(result.decode("utf-8"))) def test_setup_with_option_logging(self): """We don't mix info or debug logs with a -v option""" exception_raised = False try: subprocess.check_output(self.command_as_list([UMAKE, '-vouep', '--help']), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: self.assertNotIn("INFO:", self.return_without_first_output(e.output.decode("utf-8"))) self.assertNotIn("DEBUG:", self.return_without_first_output(e.output.decode("utf-8"))) exception_raised = True self.assertTrue(exception_raised) def test_setup_logging_level_with_env(self): """Set logging option to debug via env var""" env = {"LOG_CFG": os.path.join(get_root_dir(), "confs", "info.logcfg")} env.update(os.environ) commands = [UMAKE] if self.in_container: commands.insert(0, "LOG_CFG={}".format(env["LOG_CFG"])) result = subprocess.check_output(self.command_as_list(commands), env=env, stderr=subprocess.STDOUT) self.assertIn("Logging level set to INFO", result.decode("utf-8")) def test_version(self): """We display a version""" result = subprocess.check_output(self.command_as_list([UMAKE, '--version'])) self.assertNotEqual(result, "") def test_category_help(self): """We display a category help""" result = subprocess.check_output(self.command_as_list([UMAKE, 'ide', '--help'])) self.assertNotEqual(result, "") def test_framework_help(self): """We display a framework help""" result = subprocess.check_output(self.command_as_list([UMAKE, 'ide', 'pycharm', '--help'])) self.assertNotEqual(result, "") def test_help_position_matters(self): """The help option position matters""" result1 = subprocess.check_output(self.command_as_list([UMAKE, 'ide', 'pycharm', '--help'])) result2 = subprocess.check_output(self.command_as_list([UMAKE, 'ide', '--help', 'pycharm'])) result3 = subprocess.check_output(self.command_as_list([UMAKE, '--help', 'ide', 'pycharm'])) self.assertNotEquals(result1, result2) self.assertNotEquals(result2, result3) self.assertNotEquals(result1, result3) def test_category_with_default_framework_help(self): """We display a help when there is a default framework""" result = subprocess.check_output(self.command_as_list([UMAKE, 'android', '--help'])) self.assertNotEqual(result, "") def test_only_category_help_with_default_framework(self): """We display a category help which is different from the default framework one""" result1 = subprocess.check_output(self.command_as_list([UMAKE, 'android', '--help'])) result2 = subprocess.check_output(self.command_as_list([UMAKE, 'android', 'android-studio', '--help'])) self.assertNotEquals(result1, result2) ubuntu-make-16.11.1ubuntu1/tests/large/test_ide.py0000664000000000000000000006072513013560574016756 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # Tin Tvrtković # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the IDE category""" import logging import platform import subprocess import os from tests.large import LargeFrameworkTests from tests.tools import UMAKE, spawn_process logger = logging.getLogger(__name__) class EclipseJavaIDETests(LargeFrameworkTests): """The Eclipse distribution from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse") self.desktop_filename = "eclipse-java.desktop" self.command_args = '{} ide eclipse'.format(UMAKE) self.name = "Eclipse" @property def arch_option(self): """we return the expected arch call on command line""" return platform.machine() def test_default_eclipse_ide_install(self): """Install eclipse from scratch test case""" self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # on 64 bits, there is a java subprocess, we kill that one with SIGKILL (eclipse isn't reliable on SIGTERM) if self.arch_option == "x86_64": self.check_and_kill_process(["java", self.arch_option, self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) else: self.check_and_kill_process([self.exec_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("{} is already installed.*\[.*\] ".format(self.name)) self.child.sendline() self.wait_and_close() class EclipseJEEIDETests(EclipseJavaIDETests): """The Eclipse distribution from the IDE collection.""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse-jee") self.desktop_filename = "eclipse-jee.desktop" self.command_args = '{} ide eclipse-jee'.format(UMAKE) self.name = "Eclipse JEE" class EclipsePHPIDETests(EclipseJavaIDETests): """The Eclipse distribution from the IDE collection.""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse-php") self.desktop_filename = "eclipse-php.desktop" self.command_args = '{} ide eclipse-php'.format(UMAKE) self.name = "Eclipse PHP" class EclipseCPPIDETests(EclipseJavaIDETests): """The Eclipse distribution from the IDE collection.""" def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse-cpp") self.desktop_filename = "eclipse-cpp.desktop" self.command_args = '{} ide eclipse-cpp'.format(UMAKE) self.name = "Eclipse CPP" class IdeaIDETests(LargeFrameworkTests): """IntelliJ Idea from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "idea") self.desktop_filename = 'jetbrains-idea-ce.desktop' self.command_args = '{} ide idea'.format(UMAKE) self.name = 'Idea' def test_default_install(self): """Install from scratch test case""" self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["java", self.installed_path], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("{} is already installed.*\[.*\] ".format(self.name)) self.child.sendline() self.wait_and_close() def test_eap_install(self): self.installed_path += '-eap' self.desktop_filename.replace('.desktop', '-eap.desktop') self.command_args += ' --eap' self.name += ' EAP' self.child = spawn_process(self.command(self.command_args)) result = self.expect_and_no_warn(["ERROR: No EAP version available.*\[.*\]", "Choose installation path: {}".format(self.installed_path)]) if result == 1: self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(self.exec_path, wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("{} is already installed.*\[.*\] ".format(self.name)) self.child.sendline() self.wait_and_close() class IdeaUltimateIDETests(IdeaIDETests): """IntelliJ Idea Ultimate from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "idea-ultimate") self.desktop_filename = 'jetbrains-idea.desktop' self.command_args = '{} ide idea-ultimate'.format(UMAKE) self.name = 'Idea Ultimate' class PyCharmIDETests(IdeaIDETests): """PyCharm from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "pycharm") self.desktop_filename = 'jetbrains-pycharm-ce.desktop' self.command_args = '{} ide pycharm'.format(UMAKE) self.name = 'PyCharm' class PyCharmEducationalIDETests(IdeaIDETests): """PyCharm Educational from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "pycharm-educational") self.desktop_filename = 'jetbrains-pycharm-edu.desktop' self.command_args = '{} ide pycharm-educational'.format(UMAKE) self.name = 'PyCharm Educational' class PyCharmProfessionalIDETests(IdeaIDETests): """PyCharm Professional from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "pycharm-professional") self.desktop_filename = 'jetbrains-pycharm.desktop' self.command_args = '{} ide pycharm-professional'.format(UMAKE) self.name = 'PyCharm Professional' class RubyMineIDETests(IdeaIDETests): """RubyMine from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "rubymine") self.desktop_filename = 'jetbrains-rubymine.desktop' self.command_args = '{} ide rubymine'.format(UMAKE) self.name = 'RubyMine' class WebStormIDETests(IdeaIDETests): """WebStorm from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "webstorm") self.desktop_filename = 'jetbrains-webstorm.desktop' self.command_args = '{} ide webstorm'.format(UMAKE) self.name = 'WebStorm' class PhpStormIDETests(IdeaIDETests): """PhpStorm from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "phpstorm") self.desktop_filename = 'jetbrains-phpstorm.desktop' self.command_args = '{} ide phpstorm'.format(UMAKE) self.name = 'PhpStorm' class CLionIDETests(IdeaIDETests): """CLion test from the IDE collection""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "clion") self.desktop_filename = 'jetbrains-clion.desktop' self.command_args = '{} ide clion'.format(UMAKE) self.name = 'CLion' class DataGripIDETests(IdeaIDETests): """Datagrip test from the IDE collection""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "datagrip") self.desktop_filename = 'jetbrains-datagrip.desktop' self.command_args = '{} ide datagrip'.format(UMAKE) self.name = 'DataGrip' class ArduinoIDETests(LargeFrameworkTests): """The Arduino Software distribution from the IDE collection.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "arduino") self.desktop_filename = "arduino.desktop" @property def arch_option(self): """we return the expected arch call on command line""" return platform.machine() def test_default_install(self): """Install the distribution from scratch test case""" self.child = spawn_process(self.command('{} ide arduino'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assertTrue(self.is_in_group("dialout")) self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["java", "processing.app.Base"], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} ide arduino'.format(UMAKE))) self.expect_and_no_warn("Arduino is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class BaseNetBeansTests(LargeFrameworkTests): """Tests for the Netbeans installer.""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "netbeans") self.desktop_filename = "netbeans.desktop" def test_default_install(self): """Install from scratch test case""" self.child = spawn_process(self.command('{} ide netbeans'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() logger.info("Installed, running...") # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["java", self.installed_path], wait_before=self.TIMEOUT_START) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} ide netbeans'.format(UMAKE))) self.expect_and_no_warn("Netbeans is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class VisualStudioCodeTest(LargeFrameworkTests): """Tests for Visual Studio Code""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "visual-studio-code") self.desktop_filename = "visual-studio-code.desktop" def test_default_install(self): """Install visual studio from scratch test case""" self.child = spawn_process(self.command('{} ide visual-studio-code'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.exec_path, self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} ide visual-studio-code'.format(UMAKE))) self.expect_and_no_warn("Visual Studio Code is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class LightTableTest(LargeFrameworkTests): """Tests for LightTable""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "lighttable") self.desktop_filename = "lighttable.desktop" self.command_args = '{} ide lighttable'.format(UMAKE) def test_default_install(self): """Install LightTable from scratch test case""" self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["LightTable", self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("LightTable is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class AtomTest(LargeFrameworkTests): """Tests for Atom""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "atom") self.desktop_filename = "atom.desktop" self.command_args = '{} ide atom'.format(UMAKE) def test_default_install(self): """Install Atom from scratch test case""" self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["atom", self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Atom is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class SpringToolsSuiteTest(LargeFrameworkTests): """Tests for Spring Tools Suite""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "spring-tools-suite") self.desktop_filename = "STS.desktop" self.command_args = '{} ide spring-tools-suite'.format(UMAKE) self.name = 'Spring Tools Suite' @property def arch_option(self): """we return the expected arch call on command line""" return platform.machine() def test_default_install(self): """Install STS from scratch test case""" return # framework disabled self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) # on 64 bits, there is a java subprocess, we kill that one with SIGKILL (eclipse isn't reliable on SIGTERM) if self.arch_option == "x86_64": self.check_and_kill_process(["java", self.arch_option, self.installed_path], wait_before=self.TIMEOUT_START, send_sigkill=True) else: self.check_and_kill_process([self.exec_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("{} is already installed.*\[.*\] ".format(self.name)) self.child.sendline() self.wait_and_close() class SublimeTextTests(LargeFrameworkTests): """Tests for Sublime Text""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 20 TIMEOUT_STOP = 20 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "ide", "sublime-text") self.desktop_filename = "sublime-text.desktop" self.command_args = '{} ide sublime-text'.format(UMAKE) def test_default_install(self): """Install Sublime Text from scratch test case""" self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher and an icon file self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process([self.exec_path], wait_before=self.TIMEOUT_START, send_sigkill=True) proc.wait(self.TIMEOUT_STOP) # ensure that it's detected as installed: self.child = spawn_process(self.command(self.command_args)) self.expect_and_no_warn("Sublime Text is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() ubuntu-make-16.11.1ubuntu1/tests/large/test_android.py0000664000000000000000000001317413013560574017631 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for android""" from . import LargeFrameworkTests import os import subprocess from ..tools import UMAKE, spawn_process class AndroidStudioTests(LargeFrameworkTests): """This will test the Android Studio base""" TIMEOUT_INSTALL_PROGRESS = 120 TIMEOUT_START = 60 TIMEOUT_STOP = 60 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "android", "android-studio") self.desktop_filename = "android-studio.desktop" def test_default_android_studio_install(self): """Install android studio from scratch test case""" self.child = spawn_process(self.command('{} android android-studio'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed launcher, added to the launcher self.assertTrue(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assert_exec_exists() self.assert_icon_exists() self.assert_exec_link_exists() # launch it, send SIGTERM and check that it exits fine proc = subprocess.Popen(self.command_as_list(self.exec_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) self.check_and_kill_process(["java", self.installed_path], wait_before=self.TIMEOUT_START) self.assertEqual(proc.wait(self.TIMEOUT_STOP), 143) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} android android-studio'.format(UMAKE))) self.expect_and_no_warn("Android Studio is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class AndroidSDKTests(LargeFrameworkTests): """This will test the Android SDK installation""" TIMEOUT_INSTALL_PROGRESS = 120 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "android", "android-sdk") @property def exec_path(self): return os.path.join(self.installed_path, "tools", "android") def test_default_android_sdk_install(self): """Install android sdk from scratch test case""" self.child = spawn_process(self.command('{} android android-sdk'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed sdk exec self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # launch it, send SIGTERM and check that it exits fine self.assertEqual(subprocess.check_call(self.command_as_list([self.exec_path, "list"]), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL), 0) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} android android-sdk'.format(UMAKE))) self.expect_and_no_warn("Android SDK is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() class AndroidNDKTests(LargeFrameworkTests): """This will test the Android NDK installation""" TIMEOUT_INSTALL_PROGRESS = 120 def setUp(self): super().setUp() self.installed_path = os.path.join(self.install_base_path, "android", "android-ndk") @property def exec_path(self): return os.path.join(self.installed_path, "ndk-build") def test_default_android_ndk_install(self): """Install android ndk from scratch test case""" self.child = spawn_process(self.command('{} android android-ndk'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn("\[I Accept.*\]") # ensure we have a license question self.child.sendline("a") self.expect_and_no_warn("Installation done", timeout=self.TIMEOUT_INSTALL_PROGRESS) self.wait_and_close() # we have an installed ndk exec self.assert_exec_exists() self.assertTrue(self.is_in_path(self.exec_path)) # ensure that it's detected as installed: self.child = spawn_process(self.command('{} android android-ndk'.format(UMAKE))) self.expect_and_no_warn("Android NDK is already installed.*\[.*\] ") self.child.sendline() self.wait_and_close() ubuntu-make-16.11.1ubuntu1/tests/daily_runs/0000775000000000000000000000000013013560574015651 5ustar ubuntu-make-16.11.1ubuntu1/tests/daily_runs/install_build_tests_depends0000775000000000000000000000051513013560574023351 0ustar #!/bin/bash # install test depends from autopkgtests requirements and build-deps # devscripts and equivs are needed for mk-build-deps apt -y --no-install-recommends install $(grep Depends debian/tests/control | tr -d , | tr -d @ | sed 's/Depends: builddeps//') devscripts equivs mk-build-deps -i -t "apt -y --no-install-recommends" ubuntu-make-16.11.1ubuntu1/tests/daily_runs/get_binary_depends0000775000000000000000000000457213013560574021434 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import argparse import sys if __name__ == '__main__': parser = argparse.ArgumentParser(description="Parse debian/control for provided binary package and echo all " "dependencies.") parser.add_argument("binary", help="binary package name to grab dependencies") args = parser.parse_args() try: in_binary_section = False in_depends_section = False depends = [] with open("debian/control") as f: for line in f.readlines(): line = line.rstrip() if line == "Package: {}".format(args.binary): in_binary_section = True if not in_binary_section: continue if line.startswith("Depends: "): line = line.replace("Depends: ", "") in_depends_section = True elif line.startswith("Recommends: "): line = line.replace("Recommends: ", "") in_depends_section = True else: # we are getting out of the depends or binary sections if not line: in_binary_section = False elif line[0] != " ": in_depends_section = False if not in_depends_section: continue line_deps = line.split(",") depends.extend([dep.strip() for dep in line_deps if (dep.strip() != "" and dep.strip()[0] != "$")]) except OSError: print("Can't find debian/control") sys.exit(1) print(" ".join(depends)) ubuntu-make-16.11.1ubuntu1/tests/tools/0000775000000000000000000000000013013560574014640 5ustar ubuntu-make-16.11.1ubuntu1/tests/tools/__init__.py0000664000000000000000000001513513013560574016756 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Common tools between tests""" # DO NOT IMPORT HERE umake.* directly, only lazy import it in function. # This file is imported by runtests, before the coverage is enabled. from io import StringIO from contextlib import contextmanager, suppress from copy import deepcopy import grp import importlib import logging import os import re import shutil import xdg.BaseDirectory import pexpect from unittest import TestCase from unittest.mock import Mock logger = logging.getLogger(__name__) BRANCH_TESTS = False DOCKER = None UMAKE = "umake" INSTALL_DIR = ".local/share/umake" SYSTEM_UMAKE_DIR = "/usr/lib/python3/dist-packages/umake" class LoggedTestCase(TestCase): """A base TestCase class which asserts if there is a warning or error unless self.expect_warn_error is True""" def setUp(self): super().setUp() self.error_warn_logs = StringIO() self.__handler = logging.StreamHandler(self.error_warn_logs) self.__handler.setLevel(logging.WARNING) logging.root.addHandler(self.__handler) self.expect_warn_error = False def tearDown(self): super().tearDown() logging.root.removeHandler(self.__handler) if self.expect_warn_error: self.assertNotEqual(self.error_warn_logs.getvalue(), "") else: self.assertEqual(self.error_warn_logs.getvalue(), "") self.error_warn_logs.close() def get_data_dir(): """Return absolute data dir path""" return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'data')) def get_root_dir(): """Return absolute project root dir path""" return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) def get_tools_helper_dir(): """Return an absolute path to where the runner helpers are""" return os.path.abspath(os.path.dirname(__file__)) def assert_files_identicals(filename1, filename2): """Assert if the files content are identical""" if open(filename1).read() != open(filename2).read(): logger.error("{}: {}\n{}: {}".format(filename1, open(filename1).read(), filename2, open(filename2).read())) raise AssertionError("{} and {} aren't identical".format(filename1, filename2)) class CopyingMock(Mock): """Mock for recording calls with mutable arguments""" def __call__(self, *args, **kwargs): args = deepcopy(args) kwargs = deepcopy(kwargs) return super().__call__(*args, **kwargs) def change_xdg_path(key, value=None, remove=False): if value: os.environ[key] = value if remove: with suppress(KeyError): os.environ.pop(key) import umake.tools importlib.reload(xdg.BaseDirectory) with suppress(KeyError): umake.tools.Singleton._instances.pop(umake.tools.ConfigHandler) umake.tools.xdg_config_home = xdg.BaseDirectory.xdg_config_home umake.tools.xdg_data_home = xdg.BaseDirectory.xdg_data_home @contextmanager def patchelem(element, attr, value): old_value = getattr(element, attr) setattr(element, attr, value) yield setattr(element, attr, old_value) def manipulate_path_env(value, remove=False): """prepend value to PATH environment. If remove is true, remove it""" path = os.environ["PATH"].split(os.pathsep) if remove: path.remove(value) else: path.insert(0, value) os.environ["PATH"] = os.pathsep.join(path) @contextmanager def swap_file_and_restore(filepath): """Let changing the file in the context manager and restore to original one if needed""" try: original_content = open(filepath).read() yield original_content finally: open(filepath, 'w').write(original_content) def set_local_umake(): global UMAKE global BRANCH_TESTS UMAKE = "./bin/umake" BRANCH_TESTS = True def get_docker_path(): global DOCKER if DOCKER is None: DOCKER = shutil.which("docker.io") if not DOCKER: DOCKER = shutil.which("docker") return DOCKER def local_which(filename): """Find filename in $PATH and return it if present""" for dir in os.environ["PATH"].split(os.pathsep): file_path = os.path.join(dir, filename) if os.path.isfile(file_path): return file_path return None def get_desktop_file_path(desktop_filename): """get the desktop file path""" if not desktop_filename: return "" from umake.tools import get_launcher_path importlib.reload(xdg.BaseDirectory) return get_launcher_path(desktop_filename) def get_path_from_desktop_file(desktop_filename, key): """get the path referred as key in the desktop filename exists""" desktop_file_path = get_desktop_file_path(desktop_filename) if not get_desktop_file_path(desktop_file_path): return "" path = "" with open(desktop_file_path) as f: for line in f: p = re.search(r'{}=(.*)'.format(key), line) with suppress(AttributeError): path = p.group(1) # sanitize the field with unescaped quotes for separator in ('"', "'", " "): elem_paths = path.split(separator) path = "" for elem in elem_paths: if not elem: continue # the separator was escaped, read the separator element if elem[-1] == "\\": elem += separator path += elem # stop for current sep at first unescaped separator if not path.endswith("\\" + separator): break return path def is_in_group(group): """return if current user is in a group""" for group_name in [g.gr_name for g in grp.getgrall() if os.environ["USER"] in g.gr_mem]: print(group_name) if group_name == group: return True return False def spawn_process(command): """return a handle to a new controllable child process""" return pexpect.spawnu(command, dimensions=(24, 250)) ubuntu-make-16.11.1ubuntu1/tests/tools/get_file_perms0000775000000000000000000000150413013560574017552 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import stat import sys print(stat.filemode(os.stat(sys.argv[1]).st_mode)) ubuntu-make-16.11.1ubuntu1/tests/tools/check_user_in_group0000775000000000000000000000167013013560574020607 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) from tests.tools import is_in_group if is_in_group(sys.argv[1]): sys.exit(0) sys.exit(1) ubuntu-make-16.11.1ubuntu1/tests/tools/get_path_from_desktop_file0000775000000000000000000000171213013560574022135 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) from tests.tools import get_path_from_desktop_file print(get_path_from_desktop_file(sys.argv[1], sys.argv[2])) ubuntu-make-16.11.1ubuntu1/tests/tools/remove_path0000775000000000000000000000154013013560574017077 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys import shutil try: os.remove(sys.argv[1]) except OSError: shutil.rmtree(sys.argv[1])ubuntu-make-16.11.1ubuntu1/tests/tools/local_server.py0000664000000000000000000002227413013560574017701 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Class enabling having a local http(s) server""" from concurrent import futures from http.server import HTTPServer, SimpleHTTPRequestHandler import http.cookies import logging import os import posixpath import ssl from . import get_data_dir import urllib import urllib.parse logger = logging.getLogger(__name__) # TO CREATE THE CERTIFICATES: # openssl req -new -x509 -nodes -days 3600 -out server.crt -keyout server.key (file the fqdn name) # cat server.key server.crt > server.pem # server loads the server.pem # put the .crt file in /usr/local/share/ca-certificates and run sudo update-ca-certificates class LocalHttp: """Local threaded http server. will be serving path content""" def __init__(self, path, multi_hosts=False, use_ssl=[], port=9876, ftp_redir=False): """path is the local path to server multi_hosts will transfer http://hostname/foo to path/hostname/foo. This is used when we potentially serve multiple paths. set use_ssl to a specific array of hostnames. We'll use the corresponding certificates. """ self.port = port self.path = path self.use_ssl = use_ssl handler = RequestHandler handler.root_path = path handler.multi_hosts = multi_hosts handler.ftp_redir = ftp_redir # can be TCPServer, but we don't have a self.httpd.server_name then self.httpd = HTTPServer(("", self.port), RequestHandler) handler.hostname = self.httpd.server_name # create ssl certificate handling for SNI case (switching between different host name) self.ssl_contexts = {} context_associated = False for hostname in self.use_ssl: pem_file = os.path.join(get_data_dir(), "{}.pem".format(hostname)) if os.path.isfile(pem_file): context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) context.load_cert_chain(pem_file) self.ssl_contexts[hostname] = context if not context_associated: context_associated = True self.httpd.socket = context.wrap_socket(self.httpd.socket, server_side=True) context.set_servername_callback(self._match_sni_context) executor = futures.ThreadPoolExecutor(max_workers=1) self.future = executor.submit(self._serve) def _match_sni_context(self, ssl_sock, server_name, initial_context): """return matching certificates to the current request""" logger.info("Request on {}".format(server_name)) try: ssl_sock.context = self.ssl_contexts[server_name] except KeyError: logger.warning("Didn't find corresponding context on this server for {}, keeping default" .format(server_name)) def _serve(self): logger.info("Serving locally from {} on {}".format(self.path, self.get_address())) self.httpd.serve_forever() def get_address(self, localhost=False): """Get public address""" server_name = 'localhost' if localhost else self.httpd.server_name return "http{}://{}:{}".format("s" if self.use_ssl else "", server_name, self.port) def stop(self): """Stop local server""" logger.info("Stopping serving on {}".format(self.port)) self.httpd.shutdown() self.httpd.socket.close() class RequestHandler(SimpleHTTPRequestHandler): root_path = os.getcwd() def __init__(self, request, client_address, server): self.headers_to_send = [] super().__init__(request, client_address, server) def end_headers(self): """don't send Content-Length header for a particular file""" # we can send 404, so ensure that we have a valid path attribute if hasattr(self, "path") and self.path.endswith("-with-no-content-length"): for current_header in self._headers_buffer: if current_header.decode("UTF-8").startswith("Content-Length"): self._headers_buffer.remove(current_header) for key, value in self.headers_to_send: self.send_header(key, value) super().end_headers() def translate_path(self, path): """translate path given routes Most of it is a copy of the parent function which can't be override and uses cwd """ # Before we actually abandon the query params, see if they match an # actual file. # Need to strip the leading '/' so the join will actually work. current_root_path = RequestHandler.root_path if RequestHandler.multi_hosts: current_root_path = os.path.join(RequestHandler.root_path, self.headers["Host"].split(":")[0]) file_path = posixpath.normpath(urllib.parse.unquote(path))[1:] file_path = os.path.join(current_root_path, file_path) if os.path.exists(file_path): return file_path # abandon query parameters path = path.split('?', 1)[0] path = path.split('#', 1)[0] path = path.split('&', 1)[0] # Don't forget explicit trailing slash when normalizing. Issue17324 trailing_slash = path.rstrip().endswith('/') path = posixpath.normpath(urllib.parse.unquote(path)) words = path.split('/') words = filter(None, words) # root path isn't cwd but the one we specified and translated path = current_root_path for word in words: drive, word = os.path.splitdrive(word) head, word = os.path.split(word) if word in (os.curdir, os.pardir): continue path = os.path.join(path, word) if trailing_slash: path += '/' return path def do_GET(self): """Override this to enable redirecting paths that end in -redirect or rewrite in presence of ?file=""" cookies = http.cookies.SimpleCookie(self.headers['Cookie']) if 'int' in cookies: cookies['int'] = int(cookies['int'].value) + 1 for cookie in cookies.values(): self.headers_to_send.append(('Set-Cookie', cookie.OutputString(None))) if self.path.endswith('-redirect'): self.send_response(302) self.send_header('Location', self.path[:-len('-redirect')]) self.end_headers() elif 'setheaders' in self.path: # For paths that end with '-setheaders', we fish out the headers from the query # params and set them. url = urllib.parse.urlparse(self.path) params = urllib.parse.parse_qs(url.query) for key, values in params.items(): for value in values: self.headers_to_send.append((key, value)) # Now we need to chop off the '-setheaders' part. self.path = url.path[:-len('-setheaders')] super().do_GET() elif 'headers' in self.path: # For paths that end with '-headers', we check if the request actually # contains the header with the specified value. The expected header key # and value are in the query params. url = urllib.parse.urlparse(self.path) params = urllib.parse.parse_qs(url.query) for key in params: if self.headers[key] != params[key][0]: self.send_error(404) # Now we need to chop off the '-headers' part. self.path = url.path[:-len('-headers')] super().do_GET() else: # keep special ?file= to redirect the query if '?file=' in self.path: self.path = self.path.split('?file=', 1)[1] self.path = self.path.replace('&', '?', 1) # Replace the first & with ? to make it valid. if RequestHandler.ftp_redir: self.send_response(302) # We need to remove the query parameters, so we actually parse the URL. parsed_url = urllib.parse.urlparse(self.path) new_loc = 'ftp://' + RequestHandler.hostname + parsed_url.path self.send_header('Location', new_loc) self.end_headers() return super().do_GET() def log_message(self, fmt, *args): """Log an arbitrary message. override from SimpleHTTPRequestHandler to not output to stderr but log in the logging system """ logger.debug("%s - - [%s] %s\n" % (self.address_string(), self.log_date_time_string(), fmt % args)) ubuntu-make-16.11.1ubuntu1/tests/tools/path_exists0000775000000000000000000000150113013560574017116 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys if os.path.exists(sys.argv[1]): sys.exit(0) sys.exit(1) ubuntu-make-16.11.1ubuntu1/tests/tools/run_in_umake_dir_async0000775000000000000000000000162613013560574021302 0ustar #!/bin/bash # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # setup dbus environment and launch a command, pwd being the umake dir. # Start command in async mode cd $1 shift [[ $(env | grep VIRTUAL_ENV) == *env ]] && . env/bin/activate export $(dbus-launch) $@ & ubuntu-make-16.11.1ubuntu1/tests/tools/check_launcher_exists_and_is_pinned0000775000000000000000000000173413013560574024002 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) from umake.tools import launcher_exists_and_is_pinned if launcher_exists_and_is_pinned(sys.argv[1]): sys.exit(0) sys.exit(1) ubuntu-make-16.11.1ubuntu1/tests/tools/get_launcher_path0000775000000000000000000000166313013560574020250 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) from tests.tools import get_desktop_file_path print(get_desktop_file_path(sys.argv[1])) ubuntu-make-16.11.1ubuntu1/tests/tools/sign-asset0000775000000000000000000000141413013560574016643 0ustar #!/bin/sh set -e usage="$(basename "$0") [-h] file_to_sign asc_public_sig -- create a temporary gpg key, sign and publish a public signature where: -h show this help text file_to_sign: path to the file to sign with this new gpg key. a .sig file alongside will be created. asc_public_sig: path to the public gpg key signature. This one will be appended A temporary gpg key is created and then deleted" if [ $# -ne 2 ] || [ $1 = '-h' ] || [ $2 = '-h' ]; then echo "$usage" exit fi tmpdir=`mktemp -d` chmod 700 $tmpdir gpg --homedir $tmpdir --gen-key --batch << EOF Key-Type: DSA Name-Email: ubuntu-make@ubuntu.com Expire-Date: 0 EOF gpg --homedir $tmpdir --armor -b --sign $1 mv $1.asc $1.sig gpg --homedir $tmpdir --armor --export >> $2 rm -rf $tmpdir ubuntu-make-16.11.1ubuntu1/tests/tools/check_and_kill_process0000775000000000000000000000301013013560574021230 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from contextlib import suppress import os import signal import sys kill_process = sys.argv[1] == "True" process_grep = sys.argv[2:] for pid in os.listdir('/proc'): if not pid.isdigit() or int(pid) == os.getpid(): continue # ignore processes that are closed in between with suppress(IOError): cmdline = open(os.path.join('/proc', pid, 'cmdline'), 'r').read() for process_elem in process_grep: if process_elem not in cmdline or "run_in_umake_dir" in cmdline or sys.argv[0] in cmdline: break # we found it else: signal_to_send = signal.SIGTERM if kill_process: signal_to_send = signal.SIGKILL os.kill(int(pid), signal_to_send) sys.exit(0) sys.exit(1) ubuntu-make-16.11.1ubuntu1/tests/tools/run_in_umake_dir0000775000000000000000000000151413013560574020101 0ustar #!/bin/bash # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA cd $1 shift [[ $(env | grep VIRTUAL_ENV) == *env ]] && . env/bin/activate export $(dbus-launch) command=$@ bash -l -c "$command" ubuntu-make-16.11.1ubuntu1/tests/tools/run_local_server0000775000000000000000000000260713013560574020137 0ustar #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import logging import os import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import sys from tools import get_data_dir from tools.local_server import LocalHttp logging.basicConfig(level=logging.DEBUG, format="%(asctime)s [%(name)s] %(levelname)s: %(message)s") # start a connection hostname = sys.argv[2] ftp_redir = (sys.argv[2].lower() == 'true') server_dir = os.path.join(get_data_dir(), "server-content") LocalHttp(server_dir, multi_hosts=True, port=int(sys.argv[1]), use_ssl=sys.argv[3:], ftp_redir=ftp_redir) ubuntu-make-16.11.1ubuntu1/tests/jenkins/0000775000000000000000000000000013013560574015141 5ustar ubuntu-make-16.11.1ubuntu1/tests/jenkins/trunk-setup.xml0000664000000000000000000000744613013560574020177 0ustar Setup ubuntu make trusty job using ubuntu make trunk false 100 true false false false 2 */6 * * * false label ps-trusty-desktop-amd64-1 ps-trusty-desktop-i386-1 #!/bin/bash -eu CONFIG_PATH=/tmp/config # cleanup rm -rf ~/ubuntu-make* rm -rf ${CONFIG_PATH} # add ppa for external content assets like jayatana sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make # add test packages sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make-builddeps sudo apt update sudo apt upgrade -y # install VCS and stats tools sudo apt install -y git sloccount # clone from trunk cd ~ git clone https://github.com/ubuntu/ubuntu-make cd ubuntu-make UBUNTU_MAKE_VERSION=$(git rev-parse HEAD) # install deps from debian/control sudo apt install -y $(tests/daily_runs/get_binary_depends ubuntu-make) # install test packages sudo tests/daily_runs/install_build_tests_depends sudo addgroup $(whoami) docker # ensure docker is using the CI proxy sudo bash -c 'echo export http_proxy="http://squid.internal:3128" >> /etc/default/docker.io' sudo restart docker # config save mkdir ${CONFIG_PATH} cd ${CONFIG_PATH} echo -e "{\n 'target': 'trunk',\n 'version': '${UBUNTU_MAKE_VERSION}',\n 'date': {\n 'timestamp': '$(date +%s)',\n 'utc': '$(date -u)' },\n 'arch': &apoapos;$(arch)'\n}" > ubuntu-make-version dpkg -l > packages_list target=trunk tests, UNSTABLE_OR_BETTER false ps-trusty-desktop-revert-snapshot-daily FAILED true false ubuntu-make-16.11.1ubuntu1/tests/jenkins/system-setup.xml0000664000000000000000000001007713013560574020352 0ustar Setup udtc trusty job using system ubuntu make false 100 true false false false 02 3,9,15,21 * * * false label ps-trusty-desktop-amd64-1 ps-trusty-desktop-i386-1 #!/bin/bash -eu CONFIG_PATH=/tmp/config # cleanup rm -rf ~/ubuntu-make* rm -rf ${CONFIG_PATH} # enable localhost ssh connection without pass ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys # add ppa for external content assets like jayatana and Ubuntu Make source package sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make sudo sed -i 's/# deb-src/deb-src/' /etc/apt/sources.list.d/ubuntu-desktop-ubuntu-make-trusty.list # add test packages sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make-builddeps sudo apt update sudo apt upgrade -y # install source and stats tools sudo apt install -y dpkg-dev sloccount # install latest system version sudo apt install -y ubuntu-make cd ~ apt-get source ubuntu-make mv ubuntu-make-* ubuntu-make cd ubuntu-make mv umake umakelocal # get umake dir out of the way for coverage report UBUNTU_MAKE_VERSION=$(dpkg-parsechangelog --show-field Version) # install test packages sudo tests/daily_runs/install_build_tests_depends sudo addgroup $(whoami) docker # ensure docker is using the CI proxy sudo bash -c 'echo export http_proxy="http://squid.internal:3128" >> /etc/default/docker.io' sudo restart docker # config save mkdir ${CONFIG_PATH} cd ${CONFIG_PATH} echo -e "{\n 'version': '${UBUNTU_MAKE_VERSION}',\n 'date': {\n 'timestamp': '$(date +%s)',\n 'utc': '$(date -u)' },\n 'arch': '$(arch)'\n}" > ubuntu-make-version dpkg -l > packages_list target=system tests, UNSTABLE_OR_BETTER false ps-trusty-desktop-revert-snapshot-daily FAILED true false ubuntu-make-16.11.1ubuntu1/tests/jenkins/ps-trusty-desktop-update-daily.xml0000664000000000000000000000313713013560574023710 0ustar false 100 true false false false false label ps-trusty-desktop-amd64-1 ps-trusty-desktop-i386-1 #!/bin/bash set -ex sudo apt-get update || sudo apt-get update || sudo apt-get update sudo apt-get dist-upgrade -y --force-yes || sudo apt-get dist-upgrade -y --force-yes || sudo apt-get dist-upgrade -y --force-yes sudo apt-get install -f -y --force-yes || sudo apt-get install -f -y --force-yes || sudo apt-get install -f -y --force-yes sudo apt-get dist-upgrade -y --force-yes || sudo apt-get dist-upgrade -y --force-yes || sudo apt-get dist-upgrade -y --force-yes false ubuntu-make-16.11.1ubuntu1/tests/jenkins/branch-setup.xml0000664000000000000000000001221613013560574020260 0ustar Setup ubuntu make trusty job using an ubuntu make branch false 100 branch git branch to test if not master, name the branch can take github url like: "https://github.com/ubuntu/ubuntu-make/tree/test_set_c", or "<repo> <branch>" like "https://github.com/ubuntu/ubuntu-make.git test_set_c" rebaseontrunk Rebase on trunk true true false false false false label ps-trusty-desktop-amd64-1 ps-trusty-desktop-i386-1 #!/bin/bash -eu CONFIG_PATH=/tmp/config # cleanup rm -rf ~/ubuntu-make* rm -rf ${CONFIG_PATH} # enable localhost ssh connection without pass ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys # add ppa for external content assets like jayatana sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make # add test packages sudo add-apt-repository -y ppa:ubuntu-desktop/ubuntu-make-builddeps sudo apt update sudo apt upgrade -y # install VCS and stats tools sudo apt install -y git sloccount # split branch name if github url given instead of "<repo> <branch>" repo=${branch%/tree/*} if [ "$repo" != "$branch" ]; then branch="${repo}.git ${branch##*/tree/}" fi # merge with trunk or clone from given branch cd ~ if [ "$rebaseontrunk" = true ]; then git config --global user.email "test@ubuntu.com" git config --global user.name "Ubuntu desktop" git clone https://github.com/ubuntu/ubuntu-make cd ubuntu-make git pull --no-edit $branch else git clone $branch ubuntu-make cd ubuntu-make fi UBUNTU_MAKE_VERSION=$(git rev-parse HEAD) # install deps from debian/control sudo apt install -y $(tests/daily_runs/get_binary_depends ubuntu-make) # install test packages sudo tests/daily_runs/install_build_tests_depends sudo addgroup $(whoami) docker # ensure docker is using the CI proxy sudo bash -c 'echo export http_proxy="http://squid.internal:3128" >> /etc/default/docker.io' sudo restart docker # config save mkdir ${CONFIG_PATH} cd ${CONFIG_PATH} echo -e "{\n 'target': 'trunk',\n 'version': '${UBUNTU_MAKE_VERSION}',\n 'date': {\n 'timestamp': '$(date +%s)',\n 'utc': '$(date -u)' },\n 'arch': '$(arch)'\n}" > ubuntu-make-version dpkg -l > packages_list target=branch tests, UNSTABLE_OR_BETTER false ps-trusty-desktop-revert-snapshot-daily FAILED true false ubuntu-make-16.11.1ubuntu1/tests/jenkins/tests-collect.xml0000664000000000000000000000572413013560574020460 0ustar Collect ubuntu make trusty tests coverage report false 100 true false false false false label ps-trusty-desktop-amd64-1 ps-trusty-desktop-i386-1 #!/bin/bash -eu # remove old artefacts. rm -rf * .* 2>/dev/null || true TESTS_RESULT_DIR=~/jenkins/workspace/tests/label/*/type for test_type in `ls $TESTS_RESULT_DIR`; do coverage_file=${TESTS_RESULT_DIR}/${test_type}/.coverage config_dir=${TESTS_RESULT_DIR}/${test_type}/config if [ -f ${coverage_file} ]; then cp ${coverage_file} .coverage.${test_type} fi # all configs are identicals if [ ! -d config ] && [ -d ${config_dir} ]; then cp -a ${config_dir} . fi done python3-coverage combine python3-coverage html -d html-coverage python3-coverage xml # print on stdout as well python3-coverage report echo Stats: cd ~/ubuntu-make mv umakelocal umake 2>/dev/null || true # for the stats in case of system tests sloccount umake/ tests/ | head -n -17 | tail -n 9 ** false true true ps-trusty-desktop-revert-snapshot-daily ALWAYS true false ubuntu-make-16.11.1ubuntu1/tests/jenkins/ps-trusty-desktop-revert-snapshot-daily.xml0000664000000000000000000001021413013560574025564 0ustar false 100 true false false false false #!/bin/bash set -ex ssh ubuntu@10.100.0.103 /usr/bin/virsh snapshot-revert ps-trusty-desktop-amd64-1 24022015 ssh ubuntu@10.100.0.103 /usr/bin/virsh snapshot-revert ps-trusty-desktop-i386-1 24022015-i386 both_started=false # start the domain until it's started and kept running (virsh will return in error if domain already started) while [ "$both_started" == false ]; do echo "trying to start both vms" both_started=true # virsh returns false is domain is already started, and so, true if just started it ssh ubuntu@10.100.0.103 /usr/bin/virsh start ps-trusty-desktop-amd64-1 && both_started=false ssh ubuntu@10.100.0.103 /usr/bin/virsh start ps-trusty-desktop-i386-1 && both_started=false sleep 60 done # trying to start the jenkins slave, and ensure they are kept running for at least one loop both_were_started=false while true; do amd64_started=true i386_started=true ssh ubuntu@ps-trusty-desktop-amd64-1 /usr/bin/sudo status jenkins-slave | grep running || amd64_started=false ssh ubuntu@ps-trusty-desktop-i386-1 /usr/bin/sudo status jenkins-slave | grep running || i386_started=false if [ "$amd64_started" = true ] && [ "$i386_started" = true ]; then if [ "$both_were_started" = true ]; then break; fi both_were_started=true fi if [ "$both_were_started" = false ]; then ssh ubuntu@ps-trusty-desktop-amd64-1 /usr/bin/sudo start jenkins-slave || true ssh ubuntu@ps-trusty-desktop-i386-1 /usr/bin/sudo start jenkins-slave || true both_were_started=false fi # Let the service restarts if they do. sleep 60 done ps-trusty-desktop-update-daily ALWAYS false false #!/bin/bash set -ex # reboot the slaves and wait for them to boot up ssh ubuntu@ps-trusty-desktop-amd64-1 /usr/bin/sudo reboot ssh ubuntu@ps-trusty-desktop-i386-1 /usr/bin/sudo reboot sleep 150 # trying to start the jenkins slave, and ensure they are kept running for at least one loop both_were_started=false while true; do amd64_started=true i386_started=true ssh ubuntu@ps-trusty-desktop-amd64-1 /usr/bin/sudo status jenkins-slave | grep running || amd64_started=false ssh ubuntu@ps-trusty-desktop-i386-1 /usr/bin/sudo status jenkins-slave | grep running || i386_started=false if [ "$amd64_started" = true ] && [ "$i386_started" = true ]; then if [ "$both_were_started" = true ]; then break; fi both_were_started=true fi if [ "$both_were_started" = false ]; then ssh ubuntu@ps-trusty-desktop-amd64-1 /usr/bin/sudo start jenkins-slave || true ssh ubuntu@ps-trusty-desktop-i386-1 /usr/bin/sudo start jenkins-slave || true both_were_started=false fi # Let the service restarts if they do. sleep 60 done ubuntu-make-16.11.1ubuntu1/tests/jenkins/tests.xml0000664000000000000000000001136213013560574017030 0ustar Tests execution for ubuntu make on trusty using latest available ubuntu make test. false 100 target Test target (system or trunk). This depends on which setup job previously executed and is just a tag here. true false false false false type pep8 small medium large label ps-trusty-desktop-amd64-1 ps-trusty-desktop-i386-1 #!/bin/bash -eu RESULT_DIR=$PWD # remove old artefacts. rm -rf * .* 2>/dev/null || true echo "Testing $type tests on ubuntu make $target" ADDITIONAL_OPTS="" if [ "$target" == "system" ]; then ADDITIONAL_OPTS="--system " fi TEST_ENV="DISPLAY=:0" # set proxy for all tests but small ones (proxy doesn't know about localhost and try to interfere) if [ "$type" != small ]; then TEST_ENV="http_proxy=http://squid.internal:3128 https_proxy=http://squid.internal:3128 $TEST_ENV" fi # we skip medium on non amd64, containers are 64 bits if [ "$type" == medium ] && [ "$(arch)" != x86_64 ]; then echo '<?xml version="1.0" encoding="UTF-8"?><testsuite name="nosetests" tests="1" errors="0" failures="0" skip="0"><testcase classname="ignore" name="medium._test_not_supported" time="0.0">{}</testcase></testsuite>' > ${RESULT_DIR}/nosetests.xml exit 0 fi # We need a pseudo tty (even if we have no input) for medium tests to pass. That's why we "ssh -t -t" # sudo su is used because tests: # 1. are better run as non root (hence su whoami) # 2. need to be able to gain sudo priviledge when installing packages ssh -o StrictHostKeyChecking=no -t -t 127.0.0.1 "sudo su $(whoami) -c 'cd ~/ubuntu-make && $TEST_ENV dbus-launch eatmydata ./runtests --coverage --publish ${ADDITIONAL_OPTS} $type'" || true # copy artefacts cd ~/ubuntu-make cp nosetests.* ${RESULT_DIR} cp .coverage ${RESULT_DIR} cp -a *coverage* ${RESULT_DIR} cp *.log ${RESULT_DIR} cp -a /tmp/config ${RESULT_DIR} ** false **/nosetests.xml false true true tests-collect, ALWAYS true false ubuntu-make-16.11.1ubuntu1/tests/data/0000775000000000000000000000000013013560574014411 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/0000775000000000000000000000000013013560574017367 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/0000775000000000000000000000000013013560574022237 5ustar ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/download_handler_arduino-1.6.5-linux32.tar.xzubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/download_handler_arduino-1.6.5-l0000664000000000000000000005267613013560574030125 0ustar Arduino - Donate

Contribute to the Arduino Software

Consider supporting the Arduino Software by contributing to its development. (US tax payers, please note this contribution is not tax deductible). Learn more on how your contribution will be used.

SINCE MARCH 10TH 2015, THE ARDUINO IDE HAS BEEN DOWNLOADED SO MANY TIMES. IMPRESSIVE! THIS IDE IS NO LONGER JUST FOR ARDUINO BOARDS. HUNDREDS OF COMPANIES AROUND THE WORLD ARE USING IT TO PROGRAM THEIR DEVICES, INCLUDING COMPATIBLES, CLONES, AND EVEN COUNTERFEIT. YOU CAN HELP ACCELERATE THE DEVELOPMENT OF THE ARDUINO IDE BY CONTRIBUTING TOWARDS THE EFFORT OF MAKING IT BETTER.

Share

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/checksums.md5sum.txt0000664000000000000000000000046513013560574026203 0ustar 65a7305053e2f20aeaf772120ba9657c arduino-1.6.5-linux32.tar.xz 65a7305053e2f20aeaf772120ba9657c arduino-1.6.5-linux64.tar.xz 035be823fa0f39a0d9b74863987137b9 arduino-1.6.5-macosx.zip c0bfb988e7998a54d60505d2fe8eb3e5 arduino-1.6.5-r2-windows.exe 134e0672f4920c01777d4d89b1733c59 arduino-1.6.5-r2-windows.zip ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/download_arduino_asset32.tar.xz0000664000000000000000000002400013013560574030277 0ustar arduino-foo/0000775000175000017500000000000012540507643013476 5ustar didrocksdidrocksarduino-foo/lib/0000775000175000017500000000000012540507543014243 5ustar didrocksdidrocksarduino-foo/lib/arduino_icon.ico0000664000175000017500000000000012540507543017376 0ustar didrocksdidrocksarduino-foo/arduino0000775000175000017500000000007112540507502015055 0ustar didrocksdidrocks#!/bin/sh $(dirname $0)/java-fake processing.app.Base arduino-foo/java-fake0000775000175000017500000000002412540034420015231 0ustar didrocksdidrocks#!/bin/sh sleep 60 ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/download_handler_arduino-1.6.5-linux64.tar.xzubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/download_handler_arduino-1.6.5-l0000664000000000000000000005267613013560574030125 0ustar Arduino - Donate

Contribute to the Arduino Software

Consider supporting the Arduino Software by contributing to its development. (US tax payers, please note this contribution is not tax deductible). Learn more on how your contribution will be used.

SINCE MARCH 10TH 2015, THE ARDUINO IDE HAS BEEN DOWNLOADED SO MANY TIMES. IMPRESSIVE! THIS IDE IS NO LONGER JUST FOR ARDUINO BOARDS. HUNDREDS OF COMPANIES AROUND THE WORLD ARE USING IT TO PROGRAM THEIR DEVICES, INCLUDING COMPATIBLES, CLONES, AND EVEN COUNTERFEIT. YOU CAN HELP ACCELERATE THE DEVELOPMENT OF THE ARDUINO IDE BY CONTRIBUTING TOWARDS THE EFFORT OF MAKING IT BETTER.

Share

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/en/0000775000000000000000000000000013013560574022641 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/en/Main/0000775000000000000000000000000013013560574023525 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/en/Main/Software0000664000000000000000000006654213013560574025257 0ustar Arduino - Software

Download the Arduino Software
ARDUINO 1.6.5
The open-source Arduino Software (IDE) makes it easy to write code and upload it to the board. It runs on Windows, Mac OS X, and Linux. The environment is written in Java and based on Processing and other open-source software.
This software can be used with any Arduino board.
Refer to the Getting Started page for Installation instructions.
ARDUINO SOFTWARE
HOURLY BUILDS

Download a preview of the incoming release with the most updated features and bugfixes. Windows
Mac OS X (Mac OSX Lion or later)
Linux 32 bit , Linux 64 bit

LAST UPDATE
14 April 2015, 08:41:16 CET
ARDUINO 1.0.6 / 1.5.x / 1.6.x
PREVIOUS RELEASES

Download the previous version of the current release, the classic Arduino 1.0.x, or the Arduino 1.5.x Beta version.

All the Arduino 00xx versions are also available for download. The Arduino IDE can be used on Windows, Linux (both 32 and 64 bits), and Mac OS X.

Source Code

Active development of the Arduino software is hosted by GitHub. See the instructions for building the code.
Source code of Arduino is available here.

Other Software
Easy Installation Procedure (recommended): Download the Upgrade Image then please follow the steps in the Yún sysupgrade tutorial.
Advanced Installation Procedure: This procedure is only recommended to advanced users who wish to completely re-flash the Yún including its U-Boot bootloader. These instructions on reflashing the base images are for reference only. Following them will void your Yún's warranty.

Packages list
The list of available packages for the Yún is available here.
See the list of changes.
Terms of Use

By downloading the software from this page, you agree to the specified terms.

THE ARDUINO SOFTWARE IS PROVIDED TO YOU "AS IS" AND WE MAKE NO EXPRESS OR IMPLIED WARRANTIES WHATSOEVER WITH RESPECT TO ITS FUNCTIONALITY, OPERABILITY, OR USE, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR INFRINGEMENT. WE EXPRESSLY DISCLAIM ANY LIABILITY WHATSOEVER FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR SPECIAL DAMAGES, INCLUDING, WITHOUT LIMITATION, LOST REVENUES, LOST PROFITS, LOSSES RESULTING FROM BUSINESS INTERRUPTION OR LOSS OF DATA, REGARDLESS OF THE FORM OF ACTION OR LEGAL THEORY UNDER WHICH THE LIABILITY MAY BE ASSERTED, EVEN IF ADVISED OF THE POSSIBILITY OR LIKELIHOOD OF SUCH DAMAGES.

Share

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.arduino.cc/download_arduino_asset64.tar.xz0000664000000000000000000002400013013560574030304 0ustar arduino-foo/0000775000175000017500000000000012540507643013476 5ustar didrocksdidrocksarduino-foo/lib/0000775000175000017500000000000012540507543014243 5ustar didrocksdidrocksarduino-foo/lib/arduino_icon.ico0000664000175000017500000000000012540507543017376 0ustar didrocksdidrocksarduino-foo/arduino0000775000175000017500000000007112540507502015055 0ustar didrocksdidrocks#!/bin/sh $(dirname $0)/java-fake processing.app.Base arduino-foo/java-fake0000775000175000017500000000002412540034420015231 0ustar didrocksdidrocks#!/bin/sh sleep 60 ubuntu-make-16.11.1ubuntu1/tests/data/server-content/biggerfile0000664000000000000000000002145013013560574021413 0ustar aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.sublimetext.com/0000775000000000000000000000000013013560574024317 5ustar ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.sublimetext.com/sublime_text_3_build_mock_x32.tar.bz2ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.sublimetext.com/sublime_text_3_build_m0000777000000000000000000000000013013560574037701 2sublime_text_3_build_mock_x64.tar.bz2ustar ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.sublimetext.com/sublime_text_3_build_mock_x64.tar.bz2ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.sublimetext.com/sublime_text_3_build_m0000664000000000000000000000043513013560574030665 0ustar BZh61AY&SYˀ)„ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.stencyl.com/0000775000000000000000000000000013013560574022450 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.stencyl.com/download/0000775000000000000000000000000013013560574024257 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.stencyl.com/download/index.html0000664000000000000000000005013713013560574026262 0ustar Download Stencyl

Download Stencyl 3.1

Build 7305 - May 23rd, 2014



Mac (10.8 and above)



Download

Windows



Download


Having trouble with the newly released 3.1? Let us know.




What's New in Stencyl 3.1?

Summary
Full Changelist

New to Stencyl? Start Here.

Follow our crash course for beginners. You'll be creating games in no time.


Want to publish to iPhone, iPad, Android & Desktop?

Stencyl is free to use for Flash publishing. Publish to iOS, Android, Windows, Mac & Linux by upgrading today.





Are you upgrading from 3.0 or later?

Uninstall your prior copy and install the new version to the same location. There is no upgrade process for games, but as always, you should back them up.


Are you upgrading an existing game from 2.0-2.2?

Read our upgrade guide and be sure to back your games up before opening them in 3.0 (or above).


Can't even run a blank game? (The game shows "Compiling" forever)

See this, then post a question on the forums.


Minimum Requirements

  • Mac OS X 10.8 (Mountain Lion) or later. Stencyl does not work on 10.7 and below.
  • Windows XP or later. Preferably not Vista.
  • Ubuntu 10 or later.

Recommended Requirements

  • Mac OS X 10.9 (Mavericks) or later. You will not be able to publish iPhone or Mac apps with 10.8 or below, starting with Stencyl 3.2.
  • Windows 7 or later. Preferably not Vista.
  • Ubuntu 12 or later.

Where did the sample games go?

They're now available on our Developer Center, so we can update them separately from a release.


Major Known Issues

  • On Mac, you must install Stencyl to a path with *no* spaces or () in it, or games will fail to run.
  • On Mac, project names must contain no spaces or () in it, or they'll fail to run.
  • Games may not auto-start on an iOS Device. You must tap the icon to launch the app when directed.





ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.stencyl.com/lin0000664000000000000000000000052613013560574023160 0ustar -Un0 @9zhq'}AJGC`~P:D]|&'klLDi#UPƥ@ )hDǚz֮-%3Wխƞ_wwfS9%oo+QEh+*_Ϟc%xM 9F+g RDVu??jiFV/Y>uMn{K/g1 EXEUs$Bc?uR;cRa7a_9&#0<-ÉhgѮ82@ oDϼrubuntu-make-16.11.1ubuntu1/tests/data/server-content/simplefile-with-no-content-length0000664000000000000000000000001413013560574025750 0ustar foo bar baz ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/0000775000000000000000000000000013013560574022176 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/0000775000000000000000000000000013013560574023326 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Atom/0000775000000000000000000000000013013560574024226 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Atom/Atom/0000775000000000000000000000000013013560574025126 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Atom/Atom/releases/0000775000000000000000000000000013013560574026731 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Atom/Atom/releases/latest0000664000000000000000000010163613013560574030157 0ustar { "url": "https://api.github.com/repos/atom/atom/releases/3384604", "assets_url": "https://api.github.com/repos/atom/atom/releases/3384604/assets", "upload_url": "https://uploads.github.com/repos/atom/atom/releases/3384604/assets{?name,label}", "html_url": "https://github.com/atom/atom/releases/tag/v1.8.0", "id": 3384604, "tag_name": "v1.8.0", "target_commitish": "1.8-releases", "name": "1.8.0", "draft": false, "author": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "prerelease": false, "created_at": "2016-06-06T21:29:19Z", "published_at": "2016-06-06T22:32:56Z", "assets": [ { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803746", "id": 1803746, "name": "atom-1.8.0-delta.nupkg", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 50310671, "download_count": 186, "created_at": "2016-06-06T22:14:56Z", "updated_at": "2016-06-06T22:15:11Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-1.8.0-delta.nupkg" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803743", "id": 1803743, "name": "atom-1.8.0-full.nupkg", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 111525622, "download_count": 615, "created_at": "2016-06-06T22:14:56Z", "updated_at": "2016-06-06T22:15:16Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-1.8.0-full.nupkg" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803494", "id": 1803494, "name": "atom-amd64.deb", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 79083138, "download_count": 9785, "created_at": "2016-06-06T21:37:42Z", "updated_at": "2016-06-06T21:37:49Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-amd64.deb" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803495", "id": 1803495, "name": "atom-amd64.tar.gz", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 79659902, "download_count": 1678, "created_at": "2016-06-06T21:37:42Z", "updated_at": "2016-06-06T21:37:50Z", "browser_download_url": "https://github.com/atom/atom/releases/download/mock/atom-amd64.tar.gz" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803625", "id": 1803625, "name": "atom-api.json", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 862495, "download_count": 163, "created_at": "2016-06-06T21:57:27Z", "updated_at": "2016-06-06T21:57:28Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-api.json" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803627", "id": 1803627, "name": "atom-mac-symbols.zip", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 293053, "download_count": 134, "created_at": "2016-06-06T21:57:27Z", "updated_at": "2016-06-06T21:57:28Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-mac-symbols.zip" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803626", "id": 1803626, "name": "atom-mac.zip", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 87042184, "download_count": 15179, "created_at": "2016-06-06T21:57:27Z", "updated_at": "2016-06-06T21:57:32Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-mac.zip" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803745", "id": 1803745, "name": "atom-windows.zip", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 109372322, "download_count": 11659, "created_at": "2016-06-06T22:14:56Z", "updated_at": "2016-06-06T22:15:16Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom-windows.zip" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803533", "id": 1803533, "name": "atom.x86_64.rpm", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 64364944, "download_count": 2830, "created_at": "2016-06-06T21:42:42Z", "updated_at": "2016-06-06T21:42:46Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/atom.x86_64.rpm" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803769", "id": 1803769, "name": "AtomSetup.exe", "label": null, "uploader": { "login": "BinaryMuse", "id": 189606, "avatar_url": "https://avatars.githubusercontent.com/u/189606?v=3", "gravatar_id": "", "url": "https://api.github.com/users/BinaryMuse", "html_url": "https://github.com/BinaryMuse", "followers_url": "https://api.github.com/users/BinaryMuse/followers", "following_url": "https://api.github.com/users/BinaryMuse/following{/other_user}", "gists_url": "https://api.github.com/users/BinaryMuse/gists{/gist_id}", "starred_url": "https://api.github.com/users/BinaryMuse/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/BinaryMuse/subscriptions", "organizations_url": "https://api.github.com/users/BinaryMuse/orgs", "repos_url": "https://api.github.com/users/BinaryMuse/repos", "events_url": "https://api.github.com/users/BinaryMuse/events{/privacy}", "received_events_url": "https://api.github.com/users/BinaryMuse/received_events", "type": "User", "site_admin": true }, "content_type": "application/x-msdownload", "state": "uploaded", "size": 109668104, "download_count": 9448, "created_at": "2016-06-06T22:18:52Z", "updated_at": "2016-06-06T22:19:54Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/AtomSetup.exe" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803768", "id": 1803768, "name": "AtomSetup.msi", "label": null, "uploader": { "login": "BinaryMuse", "id": 189606, "avatar_url": "https://avatars.githubusercontent.com/u/189606?v=3", "gravatar_id": "", "url": "https://api.github.com/users/BinaryMuse", "html_url": "https://github.com/BinaryMuse", "followers_url": "https://api.github.com/users/BinaryMuse/followers", "following_url": "https://api.github.com/users/BinaryMuse/following{/other_user}", "gists_url": "https://api.github.com/users/BinaryMuse/gists{/gist_id}", "starred_url": "https://api.github.com/users/BinaryMuse/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/BinaryMuse/subscriptions", "organizations_url": "https://api.github.com/users/BinaryMuse/orgs", "repos_url": "https://api.github.com/users/BinaryMuse/repos", "events_url": "https://api.github.com/users/BinaryMuse/events{/privacy}", "received_events_url": "https://api.github.com/users/BinaryMuse/received_events", "type": "User", "site_admin": true }, "content_type": "application/octet-stream", "state": "uploaded", "size": 109498368, "download_count": 2895, "created_at": "2016-06-06T22:18:52Z", "updated_at": "2016-06-06T22:19:54Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/AtomSetup.msi" }, { "url": "https://api.github.com/repos/atom/atom/releases/assets/1803742", "id": 1803742, "name": "RELEASES", "label": "", "uploader": { "login": "mhubot", "id": 3697332, "avatar_url": "https://avatars.githubusercontent.com/u/3697332?v=3", "gravatar_id": "", "url": "https://api.github.com/users/mhubot", "html_url": "https://github.com/mhubot", "followers_url": "https://api.github.com/users/mhubot/followers", "following_url": "https://api.github.com/users/mhubot/following{/other_user}", "gists_url": "https://api.github.com/users/mhubot/gists{/gist_id}", "starred_url": "https://api.github.com/users/mhubot/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mhubot/subscriptions", "organizations_url": "https://api.github.com/users/mhubot/orgs", "repos_url": "https://api.github.com/users/mhubot/repos", "events_url": "https://api.github.com/users/mhubot/events{/privacy}", "received_events_url": "https://api.github.com/users/mhubot/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 11935, "download_count": 700, "created_at": "2016-06-06T22:14:56Z", "updated_at": "2016-06-06T22:14:56Z", "browser_download_url": "https://github.com/atom/atom/releases/download/v1.8.0/RELEASES" } ], "tarball_url": "https://api.github.com/repos/atom/atom/tarball/v1.8.0", "zipball_url": "https://api.github.com/repos/atom/atom/zipball/v1.8.0", "body": "### Notable Changes\r\n\r\n* Better environment handling\r\n* Shortcut for moving text left/right\r\n* `core.restorePreviousWindowsOnStart` setting\r\n\r\n### [Atom Core](https://github.com/atom/atom)\r\n\r\n* [atom/atom#11188 - Bump status-bar](https://github.com/atom/atom/pull/11188)\r\n* [atom/atom#11194 - Fix typo: destory -> destroy](https://github.com/atom/atom/pull/11194)\r\n* [atom/atom#11201 - Remove an unnecessary call to then().](https://github.com/atom/atom/pull/11201)\r\n* [atom/atom#11240 - More accurate block decoration measurements](https://github.com/atom/atom/pull/11240)\r\n* [atom/atom#10862 - Fix for Default Directory Provider incorrectly identifying file paths as URLs on Windows](https://github.com/atom/atom/pull/10862)\r\n* [atom/atom#11265 - fix link in ISSUE_TEMPLATE](https://github.com/atom/atom/pull/11265)\r\n* [atom/atom#11271 - Fix typo in error message.](https://github.com/atom/atom/pull/11271)\r\n* [atom/atom#11280 - Remove GitRepository git status](https://github.com/atom/atom/pull/11280)\r\n* [atom/atom#11251 - Fallback to ~/.atom/storage when no state is found in IndexedDb](https://github.com/atom/atom/pull/11251)\r\n* [atom/atom#11277 - Less disk IO](https://github.com/atom/atom/pull/11277)\r\n* [atom/atom#11296 - Improve build on Windows](https://github.com/atom/atom/pull/11296)\r\n* [atom/atom#11286 - Correctly (un)subscribe to model events on PaneAxisElement attach/detach](https://github.com/atom/atom/pull/11286)\r\n* [atom/atom#11295 - Take the submodule into account in more instances.](https://github.com/atom/atom/pull/11295)\r\n* [atom/atom#11306 - Warn rather than failing if we detect leaked pathwatcher subscriptions](https://github.com/atom/atom/pull/11306)\r\n* [atom/atom#11312 - https link to nodejs.org and visualstudio.com](https://github.com/atom/atom/pull/11312)\r\n* [atom/atom#11311 - https link to nodejs.org](https://github.com/atom/atom/pull/11311)\r\n* [atom/atom#11315 - Serialize async git](https://github.com/atom/atom/pull/11315)\r\n* [atom/atom#11320 - Update nodegit](https://github.com/atom/atom/pull/11320)\r\n* [atom/atom#6631 - Add commands to move selections left and right by one column](https://github.com/atom/atom/pull/6631)\r\n* [atom/atom#11324 - Add restorePreviousWindowsOnStart setting](https://github.com/atom/atom/pull/11324)\r\n* [atom/atom#11329 - Fix potential null reference callback invokation in script/clean](https://github.com/atom/atom/pull/11329)\r\n* [atom/atom#11325 - Fix emoji rendering on OSX](https://github.com/atom/atom/pull/11325)\r\n* [atom/atom#11316 - Add request for OS and version to Issue Template](https://github.com/atom/atom/pull/11316)\r\n* [atom/atom#11314 - Handle auto-updater errors](https://github.com/atom/atom/pull/11314)\r\n* [atom/atom#11341 - Use application-level events to control updates in the browser process](https://github.com/atom/atom/pull/11341)\r\n* [atom/atom#11339 - HTTPS a couple of links](https://github.com/atom/atom/pull/11339)\r\n* [atom/atom#11345 - Disable zoom every time a display gets added or removed](https://github.com/atom/atom/pull/11345)\r\n* [atom/atom#11351 - :arrow_up: language-perl@0.33.0](https://github.com/atom/atom/pull/11351)\r\n* [atom/atom#11246 - Improve the Windows build process](https://github.com/atom/atom/pull/11246)\r\n* [atom/atom#11369 - :racehorse: Avoid setting hidden input value on textInput](https://github.com/atom/atom/pull/11369)\r\n* [atom/atom#9554 - Add a linux archive to distribute atom](https://github.com/atom/atom/pull/9554)\r\n* [atom/atom#11398 - Fix build lint](https://github.com/atom/atom/pull/11398)\r\n* [atom/atom#11397 - Defer the callback to the next tick.](https://github.com/atom/atom/pull/11397)\r\n* [atom/atom#11403 - Fix dead atom.io/docs links in CONTRIBUTING.md](https://github.com/atom/atom/pull/11403)\r\n* [atom/atom#11410 - Use #index instead of #openIndex.](https://github.com/atom/atom/pull/11410)\r\n* [atom/atom#11418 - :memo: Add the --no-install flag to the windows build readme](https://github.com/atom/atom/pull/11418)\r\n* [atom/atom#11419 - :memo: Fix linking the decorateMarker](https://github.com/atom/atom/pull/11419)\r\n* [atom/atom#11426 - Bump nodegit](https://github.com/atom/atom/pull/11426)\r\n* [atom/atom#11412 - Signing support on Windows with P12 keys](https://github.com/atom/atom/pull/11412)\r\n* [atom/atom#11412 - Signing support on Windows with P12 keys](https://github.com/atom/atom/pull/11412)\r\n* [atom/atom#11427 - Code sign on AppVeyor](https://github.com/atom/atom/pull/11427)\r\n* [atom/atom#11436 - Allow A Window's Environment To Reflect The Most Recent atom Invocation](https://github.com/atom/atom/pull/11436)\r\n* [atom/atom#11437 - Ignore autorun on our buffered process commands. Fixes #10082](https://github.com/atom/atom/pull/11437)\r\n* [atom/atom#11438 - Don't load packages starting with a dot](https://github.com/atom/atom/pull/11438)\r\n* [atom/atom#11475 - Add ELECTRON_NO_ATTACH_CONSOLE in BufferedNodeProcess](https://github.com/atom/atom/pull/11475)\r\n* [atom/atom#11498 - Copy active item when splitting from TextEditor context menu](https://github.com/atom/atom/pull/11498)\r\n* [atom/atom#11494 - Correctly autoindent single newline in Selection#insertText](https://github.com/atom/atom/pull/11494)\r\n* [atom/atom#11463 - Fixes #11190](https://github.com/atom/atom/pull/11463)\r\n* [atom/atom#11734 - Attach msi to release on github.com](https://github.com/atom/atom/pull/11734)\r\n* [atom/atom#11552 - Content Security Policy fixes](https://github.com/atom/atom/pull/11552)\r\n\r\n### [one-dark-ui](https://github.com/atom/one-dark-ui)\r\n\r\nv1.2.0...v1.3.1\r\n\r\n* [atom/one-dark-ui#123 - Shrink modals when window gets narrow](https://github.com/atom/one-dark-ui/pull/123)\r\n* [atom/one-dark-ui#124 - Use auto-size for tabs in compact mode](https://github.com/atom/one-dark-ui/pull/124)\r\n* [atom/one-dark-ui#128 - Add tree-view bottom border](https://github.com/atom/one-dark-ui/pull/128)\r\n* [atom/one-dark-ui#131 - Add config for tab sizing](https://github.com/atom/one-dark-ui/pull/131)\r\n\r\n### [one-light-ui](https://github.com/atom/one-light-ui)\r\n\r\nv1.2.0...v1.3.1\r\n\r\n* [atom/one-light-ui#56 - Remove top border](https://github.com/atom/one-light-ui/pull/56)\r\n* [atom/one-light-ui#51 - Shrink modals when window gets narrow](https://github.com/atom/one-light-ui/pull/51)\r\n* [atom/one-light-ui#57 - Add tree-view bottom border](https://github.com/atom/one-light-ui/pull/57)\r\n* [atom/one-light-ui#58 - Add config for tab sizing](https://github.com/atom/one-light-ui/pull/58)\r\n\r\n### [solarized-dark-syntax](https://github.com/atom/solarized-dark-syntax)\r\n\r\nv1.0.0...v1.0.2\r\n\r\n* [atom/solarized-dark-syntax#63 - Rename c++ to cpp](https://github.com/atom/solarized-dark-syntax/pull/63)\r\n* [atom/solarized-dark-syntax#61 - Fix missing keywords in ruby](https://github.com/atom/solarized-dark-syntax/pull/61)\r\n\r\n### [solarized-light-syntax](https://github.com/atom/solarized-light-syntax)\r\n\r\nv1.0.0...v1.0.2\r\n\r\n* [atom/solarized-light-syntax#22 - Fix missing keywords in ruby](https://github.com/atom/solarized-light-syntax/pull/22)\r\n\r\n### [about](https://github.com/atom/about)\r\n\r\nv1.4.2...v1.5.0\r\n\r\n* [atom/about#20 - Handle update errors](https://github.com/atom/about/pull/20)\r\n\r\n### [autocomplete-css](https://github.com/atom/autocomplete-css)\r\n\r\nv0.11.0...v0.11.1\r\n\r\n* [atom/autocomplete-css#48 - Added currentColor & transparent color keywords](https://github.com/atom/autocomplete-css/pull/48)\r\n\r\n### [autocomplete-plus](https://github.com/atom/autocomplete-plus)\r\n\r\nv2.29.1...v2.29.2\r\n\r\n* [atom/autocomplete-plus#702 - Avoid deprecations introduced in atom/ns-use-display-layers branch](https://github.com/atom/autocomplete-plus/pull/702)\r\n\r\n### [bookmarks](https://github.com/atom/bookmarks)\r\n\r\nv0.38.2...v0.39.0\r\n\r\n* [atom/bookmarks#47 - Implement ranged single- and multi-line bookmarks](https://github.com/atom/bookmarks/pull/47)\r\n* [atom/bookmarks#52 - Use TextEditor APIs instead of private, deprecated displayBuffer field](https://github.com/atom/bookmarks/pull/52)\r\n* [atom/bookmarks#53 - Use MarkerLayers and refactor package](https://github.com/atom/bookmarks/pull/53)\r\n\r\n### [bracket-matcher](https://github.com/atom/bracket-matcher)\r\n\r\nv0.81.0...v0.82.0\r\n\r\n* [atom/bracket-matcher#223 - Allow scoped settings](https://github.com/atom/bracket-matcher/pull/223)\r\n\r\n### [exception-reporting](https://github.com/atom/exception-reporting)\r\n\r\nv0.37.0...v0.38.0\r\n\r\n* [atom/exception-reporting#17 - Set notifier version to version of bugsnag-atom](https://github.com/atom/exception-reporting/pull/17)\r\n\r\n### [incompatible-packages](https://github.com/atom/incompatible-packages)\r\n\r\nv0.25.1...v0.26.1\r\n\r\n* [atom/incompatible-packages#14 - Try to find the status-bar in the footer first.](https://github.com/atom/incompatible-packages/pull/14)\r\n* [atom/incompatible-packages#15 - Fix specs again](https://github.com/atom/incompatible-packages/pull/15)\r\n\r\n### [line-ending-selector](https://github.com/atom/line-ending-selector)\r\n\r\nv0.3.1...v0.4.1\r\n\r\n* [atom/line-ending-selector#25 - Try to find the status-bar in the footer first.](https://github.com/atom/line-ending-selector/pull/25)\r\n* [atom/line-ending-selector#26 - Fix specs again](https://github.com/atom/line-ending-selector/pull/26)\r\n\r\n### [snippets](https://github.com/atom/snippets)\r\n\r\nv1.0.1...v1.0.2\r\n\r\n* [atom/snippets#194 - Added more formatting options for snippets](https://github.com/atom/snippets/pull/194)\r\n\r\n### [spell-check](https://github.com/atom/spell-check)\r\n\r\nv0.67.0...v0.67.1\r\n\r\n* [atom/spell-check#122 - Add marker layers on TextEditor and stop using marker custom properties](https://github.com/atom/spell-check/pull/122)\r\n\r\n### [status-bar](https://github.com/atom/status-bar)\r\n\r\nv1.1.2...v1.2.3\r\n\r\n* [atom/status-bar#133 - Move to the footer](https://github.com/atom/status-bar/pull/133)\r\n* [atom/status-bar#134 - Use public release for CI](https://github.com/atom/status-bar/pull/134)\r\n* [atom/status-bar#138 - :racehorse: Defer updatePosition](https://github.com/atom/status-bar/pull/138)\r\n* [atom/status-bar#139 - Don't log errors caused by the repo being destroyed.](https://github.com/atom/status-bar/pull/139)\r\n* [atom/status-bar#140 - Track disposable for updatePosition](https://github.com/atom/status-bar/pull/140)\r\n* [atom/status-bar#141 - Fix spec races](https://github.com/atom/status-bar/pull/141)\r\n\r\n### [language-c](https://github.com/atom/language-c)\r\n\r\nv0.51.1...v0.51.3\r\n\r\n* [atom/language-c#128 - Add `decltype` to `storage.type.cpp`](https://github.com/atom/language-c/pull/128)\r\n* [atom/language-c#131 - Add `noexcept` to the list of storage modifiers](https://github.com/atom/language-c/pull/131)\r\n\r\n### [language-csharp](https://github.com/atom/language-csharp)\r\n\r\nv0.12.0...v0.12.1\r\n\r\n* [atom/language-csharp#59 - Add `dynamic` as a C# 4 keyword](https://github.com/atom/language-csharp/pull/59)\r\n* [atom/language-csharp#60 - Add `alias` and `global` as keywords](https://github.com/atom/language-csharp/pull/60)\r\n\r\n### [language-css](https://github.com/atom/language-css)\r\n\r\nv0.36.0...v0.36.1\r\n\r\n* [atom/language-css#54 - Added @keyframes & @supports snippet. Alphabetized](https://github.com/atom/language-css/pull/54)\r\n\r\n### [language-json](https://github.com/atom/language-json)\r\n\r\nv0.17.6...v0.18.0\r\n\r\n* [atom/language-json#45 - Mark trailing commas as syntax errors](https://github.com/atom/language-json/pull/45)\r\n\r\n### [language-less](https://github.com/atom/language-less)\r\n\r\nv0.29.0...v0.29.3\r\n\r\n* [atom/language-less#49 - Parse non-quoted relative urls](https://github.com/atom/language-less/pull/49)\r\n* [atom/language-less#53 - Add missing HTML elements](https://github.com/atom/language-less/pull/53)\r\n* [atom/language-less#55 - Fix not parsing ::shadow correctly](https://github.com/atom/language-less/pull/55)\r\n\r\n### [language-make](https://github.com/atom/language-make)\r\n\r\nv0.21.0...v0.21.1\r\n\r\n* [atom/language-make#30 - tests for comments and each function](https://github.com/atom/language-make/pull/30)\r\n* [atom/language-make#37 - Add \"mkfile\" to recognised file extensions](https://github.com/atom/language-make/pull/37)\r\n\r\n### [language-perl](https://github.com/atom/language-perl)\r\n\r\nv0.32.0...v0.34.0\r\n\r\n* [atom/language-perl#65 - Added \"n\" regex modifer (new in perl 5.22)](https://github.com/atom/language-perl/pull/65)\r\n\r\n### [language-python](https://github.com/atom/language-python)\r\n\r\nv0.43.0...v0.43.1\r\n\r\n* [atom/language-python#136 - Give self and cls the class 'variable.language.self.python'.](https://github.com/atom/language-python/pull/136)\r\n\r\n### [language-ruby](https://github.com/atom/language-ruby)\r\n\r\nv0.68.3...v0.68.5\r\n\r\n* [atom/language-ruby#141 - Add Dangerfile fileType](https://github.com/atom/language-ruby/pull/141)\r\n* [atom/language-ruby#145 - Add Brewfile to fileTypes](https://github.com/atom/language-ruby/pull/145)\r\n\r\n### [language-shellscript](https://github.com/atom/language-shellscript)\r\n\r\nv0.21.0...v0.21.1\r\n\r\n* [atom/language-shellscript#38 - Bats file support](https://github.com/atom/language-shellscript/pull/38)\r\n\r\n### [language-yaml](https://github.com/atom/language-yaml)\r\n\r\nv0.25.1...v0.25.2\r\n\r\n* [atom/language-yaml#42 - Add .clang-format as YAML file](https://github.com/atom/language-yaml/pull/42)\r\n" } ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/LightTable/0000775000000000000000000000000013013560574025345 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/LightTable/LightTable/0000775000000000000000000000000013013560574027364 5ustar ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/LightTable/LightTable/releases/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/LightTable/LightTable/rele0000775000000000000000000000000013013560574030234 5ustar ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/LightTable/LightTable/releases/latestubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/LightTable/LightTable/rele0000664000000000000000000002251213013560574030240 0ustar { "url": "https://api.github.com/repos/LightTable/LightTable/releases/2471387", "assets_url": "https://api.github.com/repos/LightTable/LightTable/releases/2471387/assets", "upload_url": "https://uploads.github.com/repos/LightTable/LightTable/releases/2471387/assets{?name,label}", "html_url": "https://github.com/LightTable/LightTable/releases/tag/mock", "id": 2471387, "tag_name": "mock", "target_commitish": "master", "name": "mock", "draft": false, "author": { "login": "kenny-evitt", "id": 1461730, "avatar_url": "https://avatars.githubusercontent.com/u/1461730?v=3", "gravatar_id": "", "url": "https://api.github.com/users/kenny-evitt", "html_url": "https://github.com/kenny-evitt", "followers_url": "https://api.github.com/users/kenny-evitt/followers", "following_url": "https://api.github.com/users/kenny-evitt/following{/other_user}", "gists_url": "https://api.github.com/users/kenny-evitt/gists{/gist_id}", "starred_url": "https://api.github.com/users/kenny-evitt/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/kenny-evitt/subscriptions", "organizations_url": "https://api.github.com/users/kenny-evitt/orgs", "repos_url": "https://api.github.com/users/kenny-evitt/repos", "events_url": "https://api.github.com/users/kenny-evitt/events{/privacy}", "received_events_url": "https://api.github.com/users/kenny-evitt/received_events", "type": "User", "site_admin": false }, "prerelease": false, "created_at": "2016-01-22T00:15:44Z", "published_at": "2016-01-22T01:12:34Z", "assets": [ { "url": "https://api.github.com/repos/LightTable/LightTable/releases/assets/1233655", "id": 1233655, "name": "lighttable-mock-linux.tar.gz", "label": null, "uploader": { "login": "rundis", "id": 399197, "avatar_url": "https://avatars.githubusercontent.com/u/399197?v=3", "gravatar_id": "", "url": "https://api.github.com/users/rundis", "html_url": "https://github.com/rundis", "followers_url": "https://api.github.com/users/rundis/followers", "following_url": "https://api.github.com/users/rundis/following{/other_user}", "gists_url": "https://api.github.com/users/rundis/gists{/gist_id}", "starred_url": "https://api.github.com/users/rundis/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/rundis/subscriptions", "organizations_url": "https://api.github.com/users/rundis/orgs", "repos_url": "https://api.github.com/users/rundis/repos", "events_url": "https://api.github.com/users/rundis/events{/privacy}", "received_events_url": "https://api.github.com/users/rundis/received_events", "type": "User", "site_admin": false }, "content_type": "application/gzip", "state": "uploaded", "size": 55599081, "download_count": 17654, "created_at": "2016-01-22T00:25:21Z", "updated_at": "2016-01-22T00:25:49Z", "browser_download_url": "https://github.com/LightTable/LightTable/releases/download/mock/lighttable-mock-linux.tar.gz" }, { "url": "https://api.github.com/repos/LightTable/LightTable/releases/assets/1233738", "id": 1233738, "name": "lighttable-mock-mac.tar.gz", "label": null, "uploader": { "login": "cldwalker", "id": 11994, "avatar_url": "https://avatars.githubusercontent.com/u/11994?v=3", "gravatar_id": "", "url": "https://api.github.com/users/cldwalker", "html_url": "https://github.com/cldwalker", "followers_url": "https://api.github.com/users/cldwalker/followers", "following_url": "https://api.github.com/users/cldwalker/following{/other_user}", "gists_url": "https://api.github.com/users/cldwalker/gists{/gist_id}", "starred_url": "https://api.github.com/users/cldwalker/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/cldwalker/subscriptions", "organizations_url": "https://api.github.com/users/cldwalker/orgs", "repos_url": "https://api.github.com/users/cldwalker/repos", "events_url": "https://api.github.com/users/cldwalker/events{/privacy}", "received_events_url": "https://api.github.com/users/cldwalker/received_events", "type": "User", "site_admin": false }, "content_type": "application/x-gzip", "state": "uploaded", "size": 57551242, "download_count": 8307, "created_at": "2016-01-22T00:52:03Z", "updated_at": "2016-01-22T00:52:42Z", "browser_download_url": "https://github.com/LightTable/LightTable/releases/download/mock/lighttable-mock-mac.tar.gz" }, { "url": "https://api.github.com/repos/LightTable/LightTable/releases/assets/1233669", "id": 1233669, "name": "lighttable-mock-windows.zip", "label": null, "uploader": { "login": "kenny-evitt", "id": 1461730, "avatar_url": "https://avatars.githubusercontent.com/u/1461730?v=3", "gravatar_id": "", "url": "https://api.github.com/users/kenny-evitt", "html_url": "https://github.com/kenny-evitt", "followers_url": "https://api.github.com/users/kenny-evitt/followers", "following_url": "https://api.github.com/users/kenny-evitt/following{/other_user}", "gists_url": "https://api.github.com/users/kenny-evitt/gists{/gist_id}", "starred_url": "https://api.github.com/users/kenny-evitt/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/kenny-evitt/subscriptions", "organizations_url": "https://api.github.com/users/kenny-evitt/orgs", "repos_url": "https://api.github.com/users/kenny-evitt/repos", "events_url": "https://api.github.com/users/kenny-evitt/events{/privacy}", "received_events_url": "https://api.github.com/users/kenny-evitt/received_events", "type": "User", "site_admin": false }, "content_type": "application/octet-stream", "state": "uploaded", "size": 58300432, "download_count": 23657, "created_at": "2016-01-22T00:28:52Z", "updated_at": "2016-01-22T00:29:00Z", "browser_download_url": "https://github.com/LightTable/LightTable/releases/download/mock/lighttable-mock-windows.zip" } ], "tarball_url": "https://api.github.com/repos/LightTable/LightTable/tarball/mock", "zipball_url": "https://api.github.com/repos/LightTable/LightTable/zipball/mock", "body": "## Changes\r\n- CHANGED: [:app :lt.objs.settings/pair-keymap-diffs] behavior is being deprecated. Use [:editor :lt.objs.editor/autoclose-brackets] in your user.behaviors instead. lt.objs.editor/autoclose-brackets should fix autoclosing characters e.g. '[{\" for international users.\r\n- CHANGED: Backspace key uses the same CodeMirror plugin that lt.objs.editor/autoclose-brackets does\r\n- CHANGED: lt.util.cljs/js->clj is being deprecated. Plugin authors can use the js->clj that comes with ClojureScript\r\n- CHANGED: Removed unused lt.objs.titlebar ns and lt.objs.titlebar/add-titlebar behavior\r\n- CHANGED: Removed unused styling in structure.css\r\n- CHANGED: Removed harbor and jshint node packages that belong to other LightTable plugins\r\n- CHANGED: Removed :hide-connect command which is the same as :show-connect\r\n- CHANGED: Removed light skin which was just a confusing pointer to dark skin\r\n- CHANGED: files/open-sync logs an error when trying to open a nonexistent file. Previously the error was ignored\r\n- CHANGED: Check for updates every hour instead of every 5 minutes\r\n- FIX: Git (vcs) friendly! Changing branches and doing rebases doesn't cause buggy dialogs. If a file is removed, the tab is closed. If a file has a local modification, the user decides whether to overwrite the current file or not\r\n- FIX: LightTable documentation supports navigation as it is now in a browser tab\r\n- FIX: Save and remove trailing whitespace behavior refreshes tab\r\n- FIX: Navigator no longer cuts off end of files i.e. can scroll horizontally\r\n- FIX: Case sensitive renaming of files e.g. readme -> README\r\n- FIX: Faster detection of binaries in build scripts\r\n- FIX: In linux, middle click to close tab doesn't paste clipboard contents\r\n- FIX: :open-path command resolves relative paths before opening them\r\n- FIX: Clearer description of font-settings behavior\r\n- FIX: Clear console error when github endpoints returns invalid JSON\r\n- FIX: All errors are consistently caught and logged to console\r\n- ADDED: Light Table builds without warnings on ClojureScript 1.7.x\r\n- ADDED: Add build target for generating cljsdeps.js (need for ClojureScript upgrade)\r\n- ADDED: Linux and Windows users have access keys on menus\r\n- ADDED: Linux and Windows users have additional menu items under File: Quit Light Table and About Light Table\r\n- ADDED: Added file type definitions for html templates: ERB, ASPX, EJS, JSP\r\n- ADDED: Command-0/Ctrl-0 to reset zoom and Command-=/Ctrl-= to zoom in\r\n- ADDED: Disply notification to user after installing/updating/uninstalling a plugin\r\n\r\n## Checksums\r\n\r\nThe MD5 checksums are reproducible on OSX and Linux with `openssl md5 FILE` and on Windows with `certUtil -hashfile FILE MD5`.\r\n\r\n - Windows – 9cdda77518e86243a52bdb88e9ddebb8\r\n - Ubuntu (14.04) - 7e4efcce58f2f4a44edb5bde6f5a91db\r\n - OSX 10.10 - 4f9fb2dd330d589a109c582a6472a4a5 " } ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Jetbrains/0000775000000000000000000000000013013560574025247 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Jetbrains/kotlin/0000775000000000000000000000000013013560574026547 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Jetbrains/kotlin/releases/0000775000000000000000000000000013013560574030352 5ustar ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Jetbrains/kotlin/releases/latestubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/Jetbrains/kotlin/releases/0000664000000000000000000001152613013560574030361 0ustar { "url": "https://api.github.com/repos/JetBrains/kotlin/releases/2613025", "assets_url": "https://api.github.com/repos/JetBrains/kotlin/releases/2613025/assets", "upload_url": "https://uploads.github.com/repos/JetBrains/kotlin/releases/2613025/assets{?name,label}", "html_url": "https://github.com/JetBrains/kotlin/releases/tag/build-1.0.0", "id": 2613025, "tag_name": "build-1.0.0", "target_commitish": "master", "name": "Kotlin 1.0.0", "draft": false, "author": { "login": "abreslav", "id": 888318, "avatar_url": "https://avatars.githubusercontent.com/u/888318?v=3", "gravatar_id": "", "url": "https://api.github.com/users/abreslav", "html_url": "https://github.com/abreslav", "followers_url": "https://api.github.com/users/abreslav/followers", "following_url": "https://api.github.com/users/abreslav/following{/other_user}", "gists_url": "https://api.github.com/users/abreslav/gists{/gist_id}", "starred_url": "https://api.github.com/users/abreslav/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/abreslav/subscriptions", "organizations_url": "https://api.github.com/users/abreslav/orgs", "repos_url": "https://api.github.com/users/abreslav/repos", "events_url": "https://api.github.com/users/abreslav/events{/privacy}", "received_events_url": "https://api.github.com/users/abreslav/received_events", "type": "User", "site_admin": false }, "prerelease": false, "created_at": "2016-02-14T21:14:19Z", "published_at": "2016-02-15T12:01:42Z", "assets": [ { "url": "https://api.github.com/repos/JetBrains/kotlin/releases/assets/1311082", "id": 1311082, "name": "kotlin-compiler-1.0.0.zip", "label": null, "uploader": { "login": "abreslav", "id": 888318, "avatar_url": "https://avatars.githubusercontent.com/u/888318?v=3", "gravatar_id": "", "url": "https://api.github.com/users/abreslav", "html_url": "https://github.com/abreslav", "followers_url": "https://api.github.com/users/abreslav/followers", "following_url": "https://api.github.com/users/abreslav/following{/other_user}", "gists_url": "https://api.github.com/users/abreslav/gists{/gist_id}", "starred_url": "https://api.github.com/users/abreslav/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/abreslav/subscriptions", "organizations_url": "https://api.github.com/users/abreslav/orgs", "repos_url": "https://api.github.com/users/abreslav/repos", "events_url": "https://api.github.com/users/abreslav/events{/privacy}", "received_events_url": "https://api.github.com/users/abreslav/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 20491203, "download_count": 2730, "created_at": "2016-02-14T21:17:55Z", "updated_at": "2016-02-14T21:18:21Z", "browser_download_url": "https://github.com/JetBrains/kotlin/releases/download/build-1.0.0/kotlin-compiler-1.0.0.zip" } ], "tarball_url": "https://api.github.com/repos/JetBrains/kotlin/tarball/build-1.0.0", "zipball_url": "https://api.github.com/repos/JetBrains/kotlin/zipball/build-1.0.0", "body": "Welcome Kotlin 1.0.0 — the first official release of the Kotlin programming language!\r\n\r\nFind installation instructions and documentation [here](https://kotlinlang.org).\r\n\r\nThis release is a result of over five years of hard work. Below, find the changes made since the [RC build](https://github.com/JetBrains/kotlin/releases/tag/build-1.0.0-rc-1036).\r\n\r\n## Library\r\n\r\n* [KT-5587](https://youtrack.jetbrains.com/issue/KT-5587) Make `Throwable#message` and `Throwable#cause` open\r\n* `kotlin.Metadata` annotation is used instead of `KotlinClass`\r\n* Old metadata annotations deleted from the `kotlin.jvm.internal` package\r\n* [KT-10462](https://youtrack.jetbrains.com/issue/KT-10462): Use HALF_EVEN rounding mode by default for BigDecimal division operator.\r\n* Default buffer size for IO operations changed to 8K (same default as in Java's `BufferedReader`).\r\n* Last deprecations dropped\r\n\r\n## Compiler\r\n\r\n* [KT-10858](https://youtrack.jetbrains.com/issue/KT-10858) Proguard issue with inline-only functions in multi-file classes\r\n* [KT-10939](https://youtrack.jetbrains.com/issue/KT-10939) CANNOT_COMPLETE_RESOLVE for inherited generic interface method\r\n* [KT-10595](https://youtrack.jetbrains.com/issue/KT-10595) Internal visibility fixed for Gradle projects in IntelliJ IDEA 16\r\n* [KT-10934](https://youtrack.jetbrains.com/issue/KT-10934) UninferredParameterTypeConstructor exception fixed for exhaustive when\r\n* [KT-10896](https://youtrack.jetbrains.com/issue/KT-10896) Wrong inference of if / else result type fixed\r\n* RoboVM incompatibility fixed" } ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/0000775000000000000000000000000013013560574025724 5ustar ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/superpowers-app/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/superpowers-ap0000775000000000000000000000000013013560574030641 5ustar ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/superpowers-app/releases/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/superpowers-ap0000775000000000000000000000000013013560574030641 5ustar ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/superpowers-app/releases/latestubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.github.com/repos/superpowers/superpowers-ap0000664000000000000000000004112013013560574030641 0ustar { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/2424025", "assets_url": "https://api.github.com/repos/superpowers/superpowers-app/releases/2424025/assets", "upload_url": "https://uploads.github.com/repos/superpowers/superpowers-app/releases/2424025/assets{?name,label}", "html_url": "https://github.com/superpowers/superpowers-app/releases/tag/vmock", "id": 2424025, "tag_name": "vmock", "target_commitish": "master", "name": "vmock — A week of Open Source", "draft": false, "author": { "login": "elisee", "id": 446986, "avatar_url": "https://avatars.githubusercontent.com/u/446986?v=3", "gravatar_id": "", "url": "https://api.github.com/users/elisee", "html_url": "https://github.com/elisee", "followers_url": "https://api.github.com/users/elisee/followers", "following_url": "https://api.github.com/users/elisee/following{/other_user}", "gists_url": "https://api.github.com/users/elisee/gists{/gist_id}", "starred_url": "https://api.github.com/users/elisee/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/elisee/subscriptions", "organizations_url": "https://api.github.com/users/elisee/orgs", "repos_url": "https://api.github.com/users/elisee/repos", "events_url": "https://api.github.com/users/elisee/events{/privacy}", "received_events_url": "https://api.github.com/users/elisee/received_events", "type": "User", "site_admin": false }, "prerelease": false, "created_at": "2016-01-14T00:18:59Z", "published_at": "2016-01-14T03:21:49Z", "assets": [ { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/assets/1308704", "id": 1308704, "name": "superpowers-mock-app.zip", "label": null, "uploader": { "login": "bilou84", "id": 11774622, "avatar_url": "https://avatars.githubusercontent.com/u/11774622?v=3", "gravatar_id": "", "url": "https://api.github.com/users/bilou84", "html_url": "https://github.com/bilou84", "followers_url": "https://api.github.com/users/bilou84/followers", "following_url": "https://api.github.com/users/bilou84/following{/other_user}", "gists_url": "https://api.github.com/users/bilou84/gists{/gist_id}", "starred_url": "https://api.github.com/users/bilou84/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/bilou84/subscriptions", "organizations_url": "https://api.github.com/users/bilou84/orgs", "repos_url": "https://api.github.com/users/bilou84/repos", "events_url": "https://api.github.com/users/bilou84/events{/privacy}", "received_events_url": "https://api.github.com/users/bilou84/received_events", "type": "User", "site_admin": false }, "content_type": "application/x-zip-compressed", "state": "uploaded", "size": 8506907, "download_count": 86, "created_at": "2016-02-13T18:46:23Z", "updated_at": "2016-02-13T18:47:38Z", "browser_download_url": "https://github.com/superpowers/superpowers-app/releases/download/vmock/superpowers-mock-app.zip" }, { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/assets/1208948", "id": 1208948, "name": "superpowers-mock-linux-ia32.zip", "label": null, "uploader": { "login": "elisee", "id": 446986, "avatar_url": "https://avatars.githubusercontent.com/u/446986?v=3", "gravatar_id": "", "url": "https://api.github.com/users/elisee", "html_url": "https://github.com/elisee", "followers_url": "https://api.github.com/users/elisee/followers", "following_url": "https://api.github.com/users/elisee/following{/other_user}", "gists_url": "https://api.github.com/users/elisee/gists{/gist_id}", "starred_url": "https://api.github.com/users/elisee/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/elisee/subscriptions", "organizations_url": "https://api.github.com/users/elisee/orgs", "repos_url": "https://api.github.com/users/elisee/repos", "events_url": "https://api.github.com/users/elisee/events{/privacy}", "received_events_url": "https://api.github.com/users/elisee/received_events", "type": "User", "site_admin": false }, "content_type": "application/x-zip-compressed", "state": "uploaded", "size": 69206121, "download_count": 402, "created_at": "2016-01-14T00:58:35Z", "updated_at": "2016-01-14T01:10:13Z", "browser_download_url": "https://github.com/superpowers/superpowers-app/releases/download/vmock/superpowers-mock-linux-ia32.zip" }, { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/assets/1209114", "id": 1209114, "name": "superpowers-mock-linux-x64.zip", "label": null, "uploader": { "login": "elisee", "id": 446986, "avatar_url": "https://avatars.githubusercontent.com/u/446986?v=3", "gravatar_id": "", "url": "https://api.github.com/users/elisee", "html_url": "https://github.com/elisee", "followers_url": "https://api.github.com/users/elisee/followers", "following_url": "https://api.github.com/users/elisee/following{/other_user}", "gists_url": "https://api.github.com/users/elisee/gists{/gist_id}", "starred_url": "https://api.github.com/users/elisee/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/elisee/subscriptions", "organizations_url": "https://api.github.com/users/elisee/orgs", "repos_url": "https://api.github.com/users/elisee/repos", "events_url": "https://api.github.com/users/elisee/events{/privacy}", "received_events_url": "https://api.github.com/users/elisee/received_events", "type": "User", "site_admin": false }, "content_type": "application/x-zip-compressed", "state": "uploaded", "size": 68747873, "download_count": 2030, "created_at": "2016-01-14T02:08:36Z", "updated_at": "2016-01-14T02:18:21Z", "browser_download_url": "https://github.com/superpowers/superpowers-app/releases/download/vmock/superpowers-mock-linux-x64.zip" }, { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/assets/1209188", "id": 1209188, "name": "superpowers-mock-osx-x64.zip", "label": null, "uploader": { "login": "elisee", "id": 446986, "avatar_url": "https://avatars.githubusercontent.com/u/446986?v=3", "gravatar_id": "", "url": "https://api.github.com/users/elisee", "html_url": "https://github.com/elisee", "followers_url": "https://api.github.com/users/elisee/followers", "following_url": "https://api.github.com/users/elisee/following{/other_user}", "gists_url": "https://api.github.com/users/elisee/gists{/gist_id}", "starred_url": "https://api.github.com/users/elisee/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/elisee/subscriptions", "organizations_url": "https://api.github.com/users/elisee/orgs", "repos_url": "https://api.github.com/users/elisee/repos", "events_url": "https://api.github.com/users/elisee/events{/privacy}", "received_events_url": "https://api.github.com/users/elisee/received_events", "type": "User", "site_admin": false }, "content_type": "application/zip", "state": "uploaded", "size": 56477197, "download_count": 2029, "created_at": "2016-01-14T02:34:28Z", "updated_at": "2016-01-14T02:42:31Z", "browser_download_url": "https://github.com/superpowers/superpowers-app/releases/download/vmock/superpowers-mock-osx-x64.zip" }, { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/assets/1209066", "id": 1209066, "name": "superpowers-mock-win-ia32.zip", "label": null, "uploader": { "login": "elisee", "id": 446986, "avatar_url": "https://avatars.githubusercontent.com/u/446986?v=3", "gravatar_id": "", "url": "https://api.github.com/users/elisee", "html_url": "https://github.com/elisee", "followers_url": "https://api.github.com/users/elisee/followers", "following_url": "https://api.github.com/users/elisee/following{/other_user}", "gists_url": "https://api.github.com/users/elisee/gists{/gist_id}", "starred_url": "https://api.github.com/users/elisee/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/elisee/subscriptions", "organizations_url": "https://api.github.com/users/elisee/orgs", "repos_url": "https://api.github.com/users/elisee/repos", "events_url": "https://api.github.com/users/elisee/events{/privacy}", "received_events_url": "https://api.github.com/users/elisee/received_events", "type": "User", "site_admin": false }, "content_type": "application/x-zip-compressed", "state": "uploaded", "size": 58303602, "download_count": 1831, "created_at": "2016-01-14T01:51:28Z", "updated_at": "2016-01-14T01:59:49Z", "browser_download_url": "https://github.com/superpowers/superpowers-app/releases/download/vmock/superpowers-mock-win-ia32.zip" }, { "url": "https://api.github.com/repos/superpowers/superpowers-app/releases/assets/1209052", "id": 1209052, "name": "superpowers-mock-win-x64.zip", "label": null, "uploader": { "login": "elisee", "id": 446986, "avatar_url": "https://avatars.githubusercontent.com/u/446986?v=3", "gravatar_id": "", "url": "https://api.github.com/users/elisee", "html_url": "https://github.com/elisee", "followers_url": "https://api.github.com/users/elisee/followers", "following_url": "https://api.github.com/users/elisee/following{/other_user}", "gists_url": "https://api.github.com/users/elisee/gists{/gist_id}", "starred_url": "https://api.github.com/users/elisee/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/elisee/subscriptions", "organizations_url": "https://api.github.com/users/elisee/orgs", "repos_url": "https://api.github.com/users/elisee/repos", "events_url": "https://api.github.com/users/elisee/events{/privacy}", "received_events_url": "https://api.github.com/users/elisee/received_events", "type": "User", "site_admin": false }, "content_type": "application/x-zip-compressed", "state": "uploaded", "size": 66509528, "download_count": 7238, "created_at": "2016-01-14T01:40:50Z", "updated_at": "2016-01-14T01:50:28Z", "browser_download_url": "https://github.com/superpowers/superpowers-app/releases/download/vmock/superpowers-mock-win-x64.zip" } ], "tarball_url": "https://api.github.com/repos/superpowers/superpowers-app/tarball/vmock", "zipball_url": "https://api.github.com/repos/superpowers/superpowers-app/zipball/vmock", "body": "## First week of Open Source\r\n\r\nIt's been almost a full week since we went open source. Some highlights:\r\n\r\n * :star2: Superpowers has been [starred over 500 times](https://github.com/superpowers/superpowers/stargazers), taking [the top weekly spot for TypeScript](https://github.com/trending?l=typescript&since=weekly)\r\n * :+1: We [were on the front page of Hacker News](https://news.ycombinator.com/item?id=10882766), [the top of r/gamedev](https://www.reddit.com/r/gamedev/comments/3zw1b2/superpowers_html5_2d3d_game_maker_going_open/) and featured in [HTML5Weekly](http://html5weekly.com/issues/222)\r\n * :heart: Our [all-new Patreon page](http://patreon.com/SparklinLabs) went from $0 to $167/month and we [received over 40 donations](sparklinlabs.itch.io/superpowers).\r\n * :octocat: 36 pull requests were submitted across all repos, 32 of them have been merged or closed\r\n * :chart_with_upwards_trend: Superpowers has been downloaded ~4000 times!\r\n\r\nWe're thrilled with the warm welcome and the many contributions popping up!\r\n\r\nAll commits in this release: https://github.com/superpowers/superpowers/compare/v0.18.1...vmock and https://github.com/superpowers/superpowers-game/compare/v0.18.1...vmock\r\n\r\n## Continuous integration!\r\n\r\nThanks to @BaptisteDixneuf (#26) and some work on our end to [correctly report build errors](https://github.com/superpowers/superpowers/commit/24b518930a4a63f2538d1961d5ff830d7a9860ad), every pull request and push made to the app repository is [now automatically checked for build errors on Travis](https://travis-ci.org/superpowers/superpowers). The other repositories will be following soon.\r\n\r\n## Registry and system installation\r\n\r\nFollowing an interesting experiment by @risq (#15), we've spent more time exploring how systems and plugins should be installed and updated. We've set up [a registry of systems and plugins](https://github.com/superpowers/superpowers/blob/master/registry.json) and added support for installing systems from the command line:\r\n\r\n```bash\r\n# List all available systems from the registry\r\nnode server install\r\n# Install Superpowers LÖVE\r\nnode server install love2d\r\n```\r\n\r\nSystem releases are automatically fetched from GitHub. Support for installing individual plugins, as well as updating it all, is planned for soon. The redesigned launcher will feature a graphical user interface to manage it all.\r\n\r\n**NOTE:** If you run your server from the command line, you must now start it with `node server start` rather than just `node server`.\r\n\r\n## Work on the redesigned launcher\r\n\r\nCoding on the [upcoming redesigned launcher](https://github.com/superpowers/superpowers-launcher) itself hasn't resumed yet but community member Kilkonie has started [a very interesting discussion](http://itch.io/t/13632/startup-sequence) and created some quality mockups:\r\n\r\n![](http://i.imgur.com/SHZtfma.png)\r\n\r\n## Noteworthy fixes and improvements in this release\r\n\r\n * **Superpowers** ([all commits](https://github.com/superpowers/superpowers/compare/v0.18.1...vmock))\r\n * The app of Superpowers is now available [in 8 different languages!](https://github.com/superpowers/superpowers/tree/master/public/locales)\r\n * There is now a 32-bit package for Linux\r\n * Dashes are now accepted in usernames and there's better feedback for invalid usernames.\r\n * You can now use an URL ending with `?build=latest` to access the latest build of a project\r\n * The Documentation tool actually displays something again\r\n * You can now open the documentation page for an editor by pressing F1 while it is focused\r\n * Cut-Copy-Paste in the OS X app has been fixed\r\n * A crash when exporting on OS X has been fixed\r\n * Worked around a major layout bug in Microsoft Edge. Oh and [Superpowers runs on Xbox One!](http://itch.io/t/13535/solved-updates-for-edge-support-further-down-the-line-pcxbox-one)\r\n * Project migration should now be more robust\r\n * Now shipping with Electron v0.36.3\r\n * **Superpowers Game** ([all commits](https://github.com/superpowers/superpowers-game/compare/v0.18.1...vmock))\r\n * The \"Stretch\" transform mode in the cubic model editor has been fixed\r\n * The API for editing shader uniforms has been improved\r\n\r\n## For plugin developers\r\n\r\n### Documentation\r\n\r\n[The documentation for extending Superpowers](http://docs.superpowers-html5.com/en/development/extending-superpowers) has been massively improved. [A repository has been created](https://github.com/superpowers/superpowers-dummy) to host a simple and heavily-commented example system. Work on it will start soon.\r\n\r\n### Setting up new systems and plugins easily\r\n\r\nThe server has gained a new command for generating the basic structure of a system or plugin:\r\n\r\n * `node server init $SYSTEM_ID` will generate a new system skeleton in `systems/$SYSTEM_ID`\r\n * `node server init $SYSTEM_ID:$AUTHOR/$NAME` will generate a new plugin skeleton in `systems/$SYSTEM_ID/plugins/$AUTHOR/$NAME`\r\n\r\n### Systems now require a `package.json` file\r\n\r\nSee Superpowers Dummy's [package.json](https://github.com/superpowers/superpowers-dummy/blob/master/package.json) for an example.\r\n\r\n * `superpowers.systemId` must contain a unique lowercase identifier for the system\r\n * `publishedPluginBundles` was added in v0.18.0 and lists the names of the Browserify-ied JavaScript bundles that should be published for runtime use for each plugin when exporting the project. Previously, this list was hard-coded." } ubuntu-make-16.11.1ubuntu1/tests/data/server-content/twinery.org/0000775000000000000000000000000013013560574021656 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/twinery.org/twine_fake_linux64.zip0000664000000000000000000002400013013560574026103 0ustar twine-foo/0000775000175000017500000000000012616634105013161 5ustar didrocksdidrockstwine-foo/Twine0000775000175000017500000000002412616634105014171 0ustar didrocksdidrocks#!/bin/sh sleep 60 ubuntu-make-16.11.1ubuntu1/tests/data/server-content/twinery.org/img/0000775000000000000000000000000013013560574022432 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/twinery.org/img/logo.svg0000664000000000000000000000000013013560574024101 0ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/twinery.org/twine_fake_linux32.zip0000777000000000000000000000000013013560574032326 2twine_fake_linux64.zipustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/twinery.org/index.html0000664000000000000000000002274713013560574023667 0ustar Twine / An open-source tool for telling interactive, nonlinear stories

Twine is an open-source tool for telling interactive, nonlinear stories.

You don't need to write any code to create a simple story with Twine, but you can extend your stories with variables, conditional logic, images, CSS, and JavaScript when you're ready.

Twine publishes directly to HTML, so you can post your work nearly anywhere. Anything you create with it is completely free to use any way you like, including for commercial purposes.

Twine was originally created by Chris Klimas in 2009 and is now maintained by a whole bunch of people at several different repositories.

Editing a story in Twine 1.4.
A bird's-eye view of a story map in Twine 1.4.
The story list in Twine 2.0.
Editing a story in Twine 2.0.

Twine has been used to create hundreds of works. Here's a sample:

Refresh Works

To have your work listed here, add it to the IFDB.

A new tool has emerged that empowers just about anyone to create a game. It's called Twine. It's extremely easy to use, and it has already given rise to a lively and diverse development scene.

Carolyn Petit, Gamespot

Although plenty of independent games venture where mainstream games fear to tread, Twine represents something even more radical: the transformation of video games into something that is not only consumed by the masses but also created by them.

Laura Hudson, The New York Times Magazine

The simple beauty of Twine is this: if you can type words and occasionally put brackets around some of those words, you can make a Twine game.

Kitty Horrorshow

If you're interested in making interactive fiction then there's no better place to start than Twine. It's possibly the simplest game making tool available, it will take you mere minutes to get started, and it has a wonderfully simple visual editor.

Richard Perrin

And aside from being free, it's really not programming at all — if you can write a story, you can make a Twine game.

Anna Anthropy

Twine is the closest we've come to a blank page. It binds itself and it can bind itself along an infinite number of spines extending in any direction.

Porpentine

@twinethreads is the official Twitter account for Twine, with news, interesting links, and new works.

If you have a link you'd like us to share, tweet at us to let us know!

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/code.visualstudio.com/0000775000000000000000000000000013013560574023610 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/code.visualstudio.com/License0000664000000000000000000003456513013560574025132 0ustar Index

MICROSOFT PRE-RELEASE SOFTWARE LICENSE TERMS

MICROSOFT VISUAL STUDIO CODE PREVIEW

These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. They apply to the software named above. The terms also apply to any Microsoft services or updates for the software, except to the extent those have additional terms.

IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.

  1. INSTALLATION AND USE RIGHTS.
    1. General. You may use the software to develop and test your applications.
    2. Demo use. The uses permitted above include use of the software in demonstrating your applications.
    3. Backup copy. You may make one backup copy of the software, for reinstalling the software.
    4. Third Party Programs.
      1. The software may include third party components with separate legal notices or governed by other agreements, as described in the ThirdPartyNotices file accompanying the software. Even if such components are governed by other agreements, the disclaimers and the limitations on and exclusions of damages below also apply.
      2. The software contains third party components licensed under open source licenses with source code availability obligations. Copies of those licenses are included in the ThirdPartyNotices file or accompanying credits file. You may obtain the complete corresponding source code from us if and as required under the relevant open source licenses by sending a money order or check for $5.00 to: Source Code Compliance Team, Microsoft Corporation, 1 Microsoft Way, Redmond, WA 98052 USA. Please write third party source code for Visual Studio Code in the memo line of your payment. We may also make the source available at http://thirdpartysource.microsoft.com/.
  2. TERM. The term of this agreement is until 30/04/2016 (day/month/year) or next public release of the software, whichever is first.
  3. PRE-RELEASE SOFTWARE. This software is a pre-release version. It may not operate correctly or work the way a final version of the software will. Microsoft may change it for the final, commercial version. Microsoft also may not release a commercial version. Microsoft is not obligated to provide maintenance, technical support or updates to you for the software.
  4. DATA. The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. For this pre-release version, users cannot opt out of data collection. Some features in the software may enable collection of data from users of applications you develop using the software. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at http://go.microsoft.com/fwlink/?LinkID=528096&clcid=0x409. Your use of the software operates as your consent to these practices.
  5. FEEDBACK. If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the right to use, share and commercialize your feedback in any way and for any purpose. You also give to third parties, without charge, any patent rights needed for their products, technologies and services to use or interface with any specific parts of a Microsoft software or service that includes the feedback. You will not give feedback that is subject to a license that requires Microsoft to license its software or documentation to third parties because we include your feedback in them. These rights survive this agreement.
  6. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not
    • work around any technical limitations in the software;
    • reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software except, and solely to the extent: (i) permitted by applicable law, despite this limitation; or (ii) required to debug changes to any libraries licensed under the GNU Lesser General Public License which are included with and linked to by the software;
    • remove, minimize, block or modify any notices of Microsoft or its suppliers in the software;
    • use the software in any way that is against the law; or
    • share, publish, or lend the software, or provide it as a hosted solution for others to use, or transfer the software or this agreement to any third party.
  7. SUPPORT SERVICES. Because this software is as is, we may not provide support services for it.
  8. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.
  9. EXPORT RESTRICTIONS. Microsoft software, online services, professional services and related technology are subject to U.S. export jurisdiction. You must comply with all applicable international and national laws including the U.S. Export Administration Regulations, the International Traffic in Arms Regulations, Office of Foreign Assets Control sanction programs, and end-user, end use and destination restrictions by the U.S. and other governments related to Microsoft products, services and technologies. For additional information, see http://www.microsoft.com/exporting.
  10. APPLICABLE LAW. If you acquired the software in the United States, Washington law applies to interpretation of and claims for breach of this agreement, and the laws of the state where you live apply to all other claims. If you acquired the software in any other country, its laws apply.
  11. LEGAL EFFECT. This agreement describes certain legal rights. You may have other rights under the laws of your state or country. This agreement does not change your rights under the laws of your state or country if the laws of your state or country do not permit it to do so. Without limitation of the foregoing, for Australia, YOU HAVE STATUTORY GUARANTEES UNDER THE AUSTRALIAN CONSUMER LAW AND NOTHING IN THESE TERMS IS INTENDED TO AFFECT THOSE RIGHTS.
  12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED AS-IS. YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  13. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.

    This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages.

* * *

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/0000775000000000000000000000000013013560574024657 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/0000775000000000000000000000000013013560574026522 5ustar ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=IIU&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000126313013560574030514 0ustar {"IIU":[{"date":"2015-12-08","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/idea/ideaIU-15.0.2.exe","size":386606040,"checksumLink":"https://download.jetbrains.com/idea/ideaIU-15.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/idea/ideaIU-15.0.2-custom-jdk-bundled.dmg","size":438180436,"checksumLink":"https://download.jetbrains.com/idea/ideaIU-15.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/idea/idea-ultimate-fake.tar.gz","size":390459277,"checksumLink":"https://data.services.jetbrains.com/idea/idea-ultimate-fake.tar.gz.sha256"}},"version":"15.0.2","majorVersion":"15.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PS&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000130013013560574030504 0ustar {"PS":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/webide/PhpStorm-10.0.2.exe","size":166004232,"checksumLink":"https://download.jetbrains.com/webide/PhpStorm-10.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/webide/PhpStorm-10.0.2-custom-jdk-bundled.dmg","size":195039438,"checksumLink":"https://download.jetbrains.com/webide/PhpStorm-10.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/phpstorm/PhpStorm-fake.tar.gz","size":212579385,"checksumLink":"https://data.services.jetbrains.com/phpstorm/PhpStorm-fake.tar.gz.sha256"}},"version":"10.0.2","majorVersion":"10.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=CL&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000122213013560574030507 0ustar {"CL":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/cpp/clion-1.2.2.exe","size":175081456,"checksumLink":"https://download.jetbrains.com/cpp/clion-1.2.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/cpp/CLion-1.2.2-custom-jdk-bundled.dmg","size":227019443,"checksumLink":"https://download.jetbrains.com/cpp/CLion-1.2.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/cpp/clion-fake.tar.gz","size":220687306,"checksumLink":"https://data.services.jetbrains.com/cpp/clion-fake.tar.gz.sha256"}},"version":"1.2.2","majorVersion":"1.2","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=IICubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000124113013560574030510 0ustar {"IIC":[{"date":"2015-12-08","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/idea/ideaIC-15.0.2.exe","size":247237112,"checksumLink":"https://download.jetbrains.com/idea/ideaIC-15.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/idea/ideaIC-15.0.2-custom-jdk-bundled.dmg","size":283902393,"checksumLink":"https://download.jetbrains.com/idea/ideaIC-15.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/idea/idea-fake.tar.gz","size":230939309,"checksumLink":"https://data.services.jetbrains.com/idea/idea-fake.tar.gz.sha256"}},"version":"15.0.2","majorVersion":"15.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PCE&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000126313013560574030514 0ustar {"PCE":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.exe","size":150777464,"checksumLink":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.dmg","size":181589445,"checksumLink":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/python/pycharm-educational-fake.tar.gz","size":117436402,"checksumLink":"https://data.services.jetbrains.com/python/pycharm-educational-fake.tar.gz.sha256"}},"version":"2.0.3","majorVersion":"2.0","build":"143.1371"}]} ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=RM&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000137713013560574030522 0ustar {"RM":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/ruby/RubyMine-8.0.2.exe","size":198777656,"checksumLink":"https://download.jetbrains.com/ruby/RubyMine-8.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/ruby/RubyMine-8.0.2-custom-jdk-bundled.dmg","size":225350927,"checksumLink":"https://download.jetbrains.com/ruby/RubyMine-8.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/ruby/rubymine-fake.tar.gz","size":175331255,"checksumLink":"https://data.services.jetbrains.com/ruby/rubymine-fake.tar.gz.sha256"}},"notesLink":"https://confluence.jetbrains.com/display/RUBYDEV/RubyMine+8.0+Kusunoki","version":"8.0.2","majorVersion":"8.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PSubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000130013013560574030504 0ustar {"PS":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/webide/PhpStorm-10.0.2.exe","size":166004232,"checksumLink":"https://download.jetbrains.com/webide/PhpStorm-10.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/webide/PhpStorm-10.0.2-custom-jdk-bundled.dmg","size":195039438,"checksumLink":"https://download.jetbrains.com/webide/PhpStorm-10.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/phpstorm/PhpStorm-fake.tar.gz","size":212579385,"checksumLink":"https://data.services.jetbrains.com/phpstorm/PhpStorm-fake.tar.gz.sha256"}},"version":"10.0.2","majorVersion":"10.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=RMubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000137713013560574030522 0ustar {"RM":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/ruby/RubyMine-8.0.2.exe","size":198777656,"checksumLink":"https://download.jetbrains.com/ruby/RubyMine-8.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/ruby/RubyMine-8.0.2-custom-jdk-bundled.dmg","size":225350927,"checksumLink":"https://download.jetbrains.com/ruby/RubyMine-8.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/ruby/rubymine-fake.tar.gz","size":175331255,"checksumLink":"https://data.services.jetbrains.com/ruby/rubymine-fake.tar.gz.sha256"}},"notesLink":"https://confluence.jetbrains.com/display/RUBYDEV/RubyMine+8.0+Kusunoki","version":"8.0.2","majorVersion":"8.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=CLubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000122213013560574030507 0ustar {"CL":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/cpp/clion-1.2.2.exe","size":175081456,"checksumLink":"https://download.jetbrains.com/cpp/clion-1.2.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/cpp/CLion-1.2.2-custom-jdk-bundled.dmg","size":227019443,"checksumLink":"https://download.jetbrains.com/cpp/CLion-1.2.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/cpp/clion-fake.tar.gz","size":220687306,"checksumLink":"https://data.services.jetbrains.com/cpp/clion-fake.tar.gz.sha256"}},"version":"1.2.2","majorVersion":"1.2","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PCPubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000136113013560574030513 0ustar {"PCP":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/python/pycharm-professional-5.0.2.exe","size":208571048,"checksumLink":"https://download.jetbrains.com/python/pycharm-professional-5.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/python/pycharm-professional-5.0.2-jdk-bundled.dmg","size":241356892,"checksumLink":"https://download.jetbrains.com/python/pycharm-professional-5.0.2-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/python/pycharm-professional-fake.tar.gz","size":187822566,"checksumLink":"https://data.services.jetbrains.com/python/pycharm-professional-fake.tar.gz.sha256"}},"version":"5.0.2","majorVersion":"5.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=IIC&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000124113013560574030510 0ustar {"IIC":[{"date":"2015-12-08","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/idea/ideaIC-15.0.2.exe","size":247237112,"checksumLink":"https://download.jetbrains.com/idea/ideaIC-15.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/idea/ideaIC-15.0.2-custom-jdk-bundled.dmg","size":283902393,"checksumLink":"https://download.jetbrains.com/idea/ideaIC-15.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/idea/idea-fake.tar.gz","size":230939309,"checksumLink":"https://data.services.jetbrains.com/idea/idea-fake.tar.gz.sha256"}},"version":"15.0.2","majorVersion":"15.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=WSubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000131013013560574030505 0ustar {"WS":[{"date":"2015-12-07","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2.exe","size":157871800,"checksumLink":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2-custom-jdk-bundled.dmg","size":183965019,"checksumLink":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/webstorm/WebStorm-fake.tar.gz","size":132160662,"checksumLink":"https://data.services.jetbrains.com/webstorm/WebStorm-fake.tar.gz.sha256"}},"version":"11.0.2","majorVersion":"11.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PCCubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000131313013560574030510 0ustar {"PCC":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/python/pycharm-community-5.0.2.exe","size":169759968,"checksumLink":"https://download.jetbrains.com/python/pycharm-community-5.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/python/pycharm-community-5.0.2-jdk-bundled.dmg","size":170811847,"checksumLink":"https://download.jetbrains.com/python/pycharm-community-5.0.2-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/python/pycharm-fake.tar.gz","size":136420461,"checksumLink":"https://data.services.jetbrains.com/python/pycharm-fake.tar.gz.sha256"}},"version":"5.0.2","majorVersion":"5.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PCP&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000136113013560574030513 0ustar {"PCP":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/python/pycharm-professional-5.0.2.exe","size":208571048,"checksumLink":"https://download.jetbrains.com/python/pycharm-professional-5.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/python/pycharm-professional-5.0.2-jdk-bundled.dmg","size":241356892,"checksumLink":"https://download.jetbrains.com/python/pycharm-professional-5.0.2-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/python/pycharm-professional-fake.tar.gz","size":187822566,"checksumLink":"https://data.services.jetbrains.com/python/pycharm-professional-fake.tar.gz.sha256"}},"version":"5.0.2","majorVersion":"5.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PCEubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000126313013560574030514 0ustar {"PCE":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.exe","size":150777464,"checksumLink":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.dmg","size":181589445,"checksumLink":"https://download.jetbrains.com/python/pycharm-edu-2.0.3.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/python/pycharm-educational-fake.tar.gz","size":117436402,"checksumLink":"https://data.services.jetbrains.com/python/pycharm-educational-fake.tar.gz.sha256"}},"version":"2.0.3","majorVersion":"2.0","build":"143.1371"}]} ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=DG&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000125613013560574030516 0ustar {"DG":[{"date":"2016-01-27","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/datagrip/datagrip-1.0.2.exe","size":127639968,"checksumLink":"https://download.jetbrains.com/datagrip/datagrip-1.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/datagrip/datagrip-1.0.2-custom-jdk-bundled.dmg","size":142337722,"checksumLink":"https://download.jetbrains.com/datagrip/datagrip-1.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/datagrip/datagrip-fake.tar.gz","size":136235809,"checksumLink":"https://data.services.jetbrains.com/datagrip/datagrip-fake.tar.gz.sha256"}},"version":"1.0.2","majorVersion":"1.0"}]}././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=WS&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000131013013560574030505 0ustar {"WS":[{"date":"2015-12-07","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2.exe","size":157871800,"checksumLink":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2-custom-jdk-bundled.dmg","size":183965019,"checksumLink":"https://download.jetbrains.com/webstorm/WebStorm-11.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/webstorm/WebStorm-fake.tar.gz","size":132160662,"checksumLink":"https://data.services.jetbrains.com/webstorm/WebStorm-fake.tar.gz.sha256"}},"version":"11.0.2","majorVersion":"11.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=IIUubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000126313013560574030514 0ustar {"IIU":[{"date":"2015-12-08","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/idea/ideaIU-15.0.2.exe","size":386606040,"checksumLink":"https://download.jetbrains.com/idea/ideaIU-15.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/idea/ideaIU-15.0.2-custom-jdk-bundled.dmg","size":438180436,"checksumLink":"https://download.jetbrains.com/idea/ideaIU-15.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/idea/idea-ultimate-fake.tar.gz","size":390459277,"checksumLink":"https://data.services.jetbrains.com/idea/idea-ultimate-fake.tar.gz.sha256"}},"version":"15.0.2","majorVersion":"15.0","build":"143.1184"}]} ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=DGubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000125613013560574030516 0ustar {"DG":[{"date":"2016-01-27","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/datagrip/datagrip-1.0.2.exe","size":127639968,"checksumLink":"https://download.jetbrains.com/datagrip/datagrip-1.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/datagrip/datagrip-1.0.2-custom-jdk-bundled.dmg","size":142337722,"checksumLink":"https://download.jetbrains.com/datagrip/datagrip-1.0.2-custom-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/datagrip/datagrip-fake.tar.gz","size":136235809,"checksumLink":"https://data.services.jetbrains.com/datagrip/datagrip-fake.tar.gz.sha256"}},"version":"1.0.2","majorVersion":"1.0"}]}././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?code=PCC&type=eapubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/products/releases?c0000664000000000000000000000131313013560574030510 0ustar {"PCC":[{"date":"2015-12-10","type":"release","downloads":{"windows":{"link":"https://download.jetbrains.com/python/pycharm-community-5.0.2.exe","size":169759968,"checksumLink":"https://download.jetbrains.com/python/pycharm-community-5.0.2.exe.sha256"},"mac":{"link":"https://download.jetbrains.com/python/pycharm-community-5.0.2-jdk-bundled.dmg","size":170811847,"checksumLink":"https://download.jetbrains.com/python/pycharm-community-5.0.2-jdk-bundled.dmg.sha256"},"linux":{"link":"https://data.services.jetbrains.com/python/pycharm-fake.tar.gz","size":136420461,"checksumLink":"https://data.services.jetbrains.com/python/pycharm-fake.tar.gz.sha256"}},"version":"5.0.2","majorVersion":"5.0","build":"143.1184"}]} ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/ruby/0000775000000000000000000000000013013560574025640 5ustar ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/ruby/rubymine-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/ruby/rubymine-fake.0000664000000000000000000000021013013560574030370 0ustar b47c7d4e0f68ce3b674623cef8fbbac5170493aa9b1899c93016fbb81d328852 tests/data/server-content/www.jetbrains.com/ruby/rubymine-fake.tar.gz ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/ruby/rubymine-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/ruby/rubymine-fake.0000664000000000000000000000420213013560574030375 0ustar wT 4Tx)rDvy=Ce"# 16sQ8oRiJ;7if 3gϞWҠɵ溇s$6 bM !B0Nsu4sDA`gu.Qk`,I+J9q+5 Q&.ڇIlݾP\S_tx+t,">^6~f]sxTXc#'sܶX \t &$Yx(4ێ7],-B.>:uY'qZ׵Chދ)f݊~fiV'=iyCAnr_e4BɌ"Y@u"9]eQ*ilPRi4uശ)I@;;.JnV1J/PX;M&ض"'8reڽoAFC]X_,֕‰xS/ (J 3Ƃ W bЉ(tM6+Kh705(<w}QU),1J=H9xEy%Tr yN$m-y|i/qYrɚmٹT삾Rx  M;@QC1nMRӛ* ''G w2抽cTP 1Nۏ1ӓZ?sd咝k;%]mkap|+y3lx䦶N});uv兽ǎ޹sOi12DSÔV1?D^^Bt66dY%Va% \*J`}y7+Z.Bk6::4UU6per'W͒UߖnDZ_HlPIN\/›д|֡ʠSg"wZcɅPbq(&Վ3Bj@8+*J) uBxՈ~D€Q]Fo:2MWG?# z[xYbPB&GQL-:<85 >UekrՉlW׵g9] Q-81c1l'm1h4Fqxp讜՜Àtus>|UF.0\ P,ՁPLR0  MIauҒ06c3)!T%l;kXG 4 ?33Amwܙ ?\AF4A"1Y0y ~?D?ƌ vRcHW?Ejq8/A?<%Cubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/datagrip/0000775000000000000000000000000013013560574026452 5ustar ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/datagrip/datagrip-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/datagrip/datagrip-f0000664000000000000000000000012713013560574030413 0ustar 9f299e74f163fe303b1882a225c30b6a63325ac3b8f6bce891d6c6bee70212b2 datagrip-fake.tar.gz ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/datagrip/datagrip-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/datagrip/datagrip-f0000664000000000000000000002565713013560574030432 0ustar V{TSݶ! t"(U:(E{OФ&MAiҤHU@:R)"ޥ79;=w1=odso~k=Ɗ%R'//,w@PPP\\ ~ mWbBbBD剱 jWqmο??O<_\O%;;Yz[Y:| !1KD?+g;DD.h8BN?ԟ7# {#. Wo~]_;G{l1h7K= DE3 a!1!a?@)o%ۇz!gwcT 0QvK[@ee jio{ϽVwQuECFmil[;ɲmke;ȲVupTa{CgkI6y9K,J]-}YepW򰅋#pqI~!1qqQpJAA>a)QA˪.yISV,Gy IJJ   ]sXyee[OK5aQn-P^Y6\+ݿNǍehK e'枭?뇶gÎo\c^F#ruReqRV嗤_lo]/n+m n'8yw5;F6JLUVr<mO8I/W_ݗB]o\Z:j}/αJliGhM(ʸPD:Sy17)\i^{-C8PKB&a)W\OT}̛-nD7.w?L7T]rAJW{tv{;Uݾԫ2X:l ~w_qyoPj&VE]|=LVB6&ugۓ?=%tC0 LsgX`qMVXpiod >fr]IϔoLZ Bحxy8FL8@[[l_H0x'`3EDS+q%j˸pH1WhO܍6f6ތ"S  } A1IQ (B99]J }=,ku[<Dt Xܨ?ʐ"#/)Y=S_Y rv2 /s*_[;˟.Ōo.(+Yu7̳vX$9PCO,K4R j͇:&o |inHaje b_2%6K-5!myi!va]0{l/v-??ϥH2uJ^eyʄ.o-ޜ7Y*I \^'CYhHaLԒ:Ǵ:/,7tOשt֐q5΃FٓʉUOV>9I`#6:a Lػڪ`J:TN,\O_qmW9x< &)29zu(x/@"Koj@ԩy2^ Ǻ)*,,u5<-4#:ߴe~|c\pdQ*j,+Z7ȍKDDPB=+cv^FNA/ڭ;IjxН~9h~0la)xqWBߘvur6h2+4,>9;Mѩ/bT^e茜 7evK8~lJ3sA|;g wRBOd<% 2W=4UY4wz({4^Ԅ:4( ?U0Z4Z{KD`sipETI4%݋9,JM@3z%(B"$I;% ɧR#zCt$&H צ##qT*\ ,4g{х(06g,ްɖ- PuDqEɖ$=἞j ApI_kI"hԋ9Yiث;zKoH8]NT$Dwrݼ>q3W/ ǍȘ11DGK/PH)ȅ)dO"Durf_~E^];zmїW𧓄Ǣ*$xҽ|bL'DC]{wpо5ӂ4b7K7%*o=ژi{)[ɜHW%%p-AP|b3gVvI؆ ӳX芫pb>jR 緎_ ' _'U0y^y\:Q't$57S+d wf Ѿw/q'g8&>;:aqx%lٿp:} JӁ.O♿! dM0fO9{| 減LFC:,axίmPB;co8kOQ]0Tv01'p#<9%-N;vomZ7w}f#6R+Τfn5ӰV^/9M=iœwdyrϞ?oo)Ш,Ezg?c_UVRn5_ߒc'v]ש6%W#/ތ3"EcI-AN:iYY/'IպM—}͒B mbGfz3x bVǯVY̴m1f (C IU~S`Q'`l9fj:G}|铵^):ٴY;1k9~f*+s~;@Sy|\ytC j.eĖ)kҝ; ZԻnM?T j]}`hƜ.|!tûiXvi0ۮ4^ ̒0BVDФAH:qz'UStN' $< ,_l Hv<$^}3UVm1C>~}[GYTltOn$a-4N?W z11:|.̰P?iXde kB2xU>@u 5zbx첞à ws01>l^D$(2 ĵSّ4k8)ÿa9'|.nDɸqsy:wo&wB٬#2# ݍYO8Ϩ҈GO3^`Q~ =Y|}OƊڞrbF'{3&y˫7+l>'Ƞ}S/Hf5Vs!$9!qJ%ɍ֬ï쥷}9 .Mnn1u#/0bPbgc|UoݩS!' Iü8ٜZO0ըeKӷruWɃ$,2XhbDc"@q\ @,=O'QysuQ1VY5><0=DbC$]wl~o1P>*oNy}q#'0P+Aбf\vrtQ5~ѳzkv8--Žر\J,pGqk~j+maB5RJ 7`5>':XҒ^rF+Ol1p߇OՌ ,^a;Q:tOD&5>AT|myKd(QXTBL>«\l obQx}ܖ,M*>LzX9vy^V+4Uuͅbա&=xHxKWد[27Vj$=d{ 2 .tPBǬM6^D܃٥W(y13P:A<]\Tu2\JgVc!þ2?}- ³\Kb&bA{l",{1,=摧&G kCqAGs#v?|FLL~qyWGx-zNAXRMPoTځPc pr.1ޣ3?ʣ8~|A:!(Ldgh~;Ak6\2F+bRϸB;]tmSɠu3Z+E dڰ20wKr^ݬ>\?;8t-_J4j(>br~/齈oi8Y+-79ڙ{}zYC r+XX 3k3_Oil@nO,+o7Ң)eGipAGp2ޭgH Zico#` KBݫN@}ϳH ݴGV xL*I?9)T&qAsWdۯy eyD((,x_:OT~- E= |K0"O_J \ ƭ7&^vկXZuߋhS!+^C׶[J}Ʋ5wm>d|i @muYD*\:z4"曚 SKHZHf5Giڎ#jIanyk_*qMR36Z/5YkYC?)# i[QZ;+ڀKhr-H(Yٙk՝"^b ~8/@@!UU Ǯ!m բH2R%yUiKR&|;I-7LAJ["'` N26ۆCY|j'ldT,|(EoFs&W Q$4 jJA皀#!z(L\mw-m ~%NԙC:乞`YZOsx$#^5igj&2*FiP{ OWkO*8)`XT rLN!8/:2 c৻ K CbF&5>&oɐ~b-WȲIfGWyY9\m$:Rs%K*GɁor.ߚ=Ro&Z[v |û)msڼnFRPrEE>p?_w[7ᕸ_+@B@{U'GGS?д g7Uza@+@լ$|CC+ |,S;x]v䡺@اཟoZ7B]m\yXc߉aVu69U]W:Am.[^ܵ4.{ݓ}>|dü6,'7mn݉*QSl8dE.)A$,D nQ)i;niB 6ї Џۗg9DOQL7z4+OZ@_ܹ.@R?&FY%m_ jhV<̃Vu ܽ/c G9[0r XմYe!}<z;nA ?@PBI,CTFCFrU %*ٸi|1|2]9-ԢkgVwh;p$9ڣ m4Fe"W3&f*?$>L8it_бЋ;t ]n!9pM_̧p-X%ثp Ȕ^1A0z?AϦLq2޳#\ijb@qaln("7TR`^'O?llo)]vŏwKӈ@͂X$AVW-/;8S 6N,$.HI')\*"&R PQ[מp$3^Qr|$ L62@T: oW@pbGI% j(C:Fizf8m +,(?͂Wl`1Rz0(@SipG7xu:_Z!{kbD}'V=hj^ Ȑ zm3;W#vիj1zuRDTa:=}Ǣ煥M '#qY۞xIF!Æޥhs^7b5jJ9 s wh;{(97w:s'CchCs.j,ZY-$J= x_L.oxicf[_^ؔu/bV\sc`'0yer\+h0Ԉj"Ą:PhQ 6(<[\AbU+ $nZ!l{S<-aR rB"Xcyx}rDD+L3_Biv;Hhm+^q 8Hd~g dp\]-Mz>f#梄.kH X)Hkq-FZτ*<c5+u ڝtt{L;uMQV+EZ #;c2c% *S[^e!!3@MܥyS cSj&? {fX'&!*Fp[ o~H~!YpW:Yw0AFF@F/@7/큒} (q9JǮp~ #;?oh|Nhꠝo)=#ȟ<)h|S&ijuŭ9“~[Ҹox/l6 ߤ W{ڎ&EtCt2wOJxT8=3`TZ{kA܉|,|dy۸Z̻4sO`5i kAE[_ #,B%C\LO޼>OfRC(?p`i# qBAE09^gq=;@C Z| 8IU'I]o,vda;%Bg'FsD݋:<KRAn҇40v\5tշ5i|f5rx/vm10Cf̂DQxH5SZ VgZnRyVL&QA }^4PvZ 3Xlwr3l|ܗS@z:$cA2,1{҈ͱO Ai̻xF 󏜷\jc /@/<0r'r]YjGr-X4ob´ESzN ٣IGR^ߘãe&tȓi3Q҉gu``B#{YKgz,].p}F[3+HKv嗆Q# 4CQñ2-Pʧ.CCq3KO;#F(vhK`Wynʡ̜^Ϯ$F,&#WVָwvŋ ݏp^B ^Z{/dZ)qoZ 0˓ 5;!|YI`қ~5T_)QxS r;~K Aͼy}׆WsS1SoHLRJDV=Sxq82@2 TV=խc_]K6^Ze`$1ZL~ .']Qb:&هJG{J;<\+O կ|,|n+4Ӧɍކd1`HgppɜI\6Ⱥ*Єu&˩ی'K4Lb(wF?t^\`Ks '0'T=F&n!7\H%ɻ]YTo-$M*#yR/|јAI !2=P Mhh#ȓ&yf!]?i@$$2޾HFD)Iݷ;jV4,ܤ)%m9˸THd݌T5dNd~J T[ i7ޱ?Hw=>̓i՜%_m>tU&5gͯMx+#;5:pk`uFPⳲ]\dقj^nw -QÒ>{\~xjW|G00w[V% fУ*_P#EBN;4y}ww>+m:'=ٴ`|Ҝu{rj.\ Ck5-mXfŞt.LS| &4WT>WPēTԪ$> A'MA߶RT~h?_ņg/!$7ПPVO?'Ŀ 2Bubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/phpstorm/0000775000000000000000000000000013013560574026533 5ustar ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/phpstorm/PhpStorm-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/phpstorm/PhpStorm-f0000664000000000000000000000012713013560574030455 0ustar ce4ee9844f0d2febfce8ac6a380d5c5429374e3144e71a4c3f5107a763dc388c PhpStorm-fake.tar.gz ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/phpstorm/PhpStorm-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/phpstorm/PhpStorm-f0000664000000000000000000010205413013560574030457 0ustar :TwUP@9 \Bpwwwwwwwwwve>lWWS353_˙Bm-X8Y~Y18234X_###++? ar#v\1436? DdĐAd qaπl hr3!!9 !!9[kcFǧ %L`k\l~5}ʊMa%b$w؃>We|a_K Tq/Ȱܖ;k%%{Q|=QjqEثu<¹y}"̫kV'W`a3 8~naajsb9Vi_XQEjŭ7>kұޙW 8C|b>\w3Iotik=ȪPgv;܃ڃʃ҃Mz3v\{= gE[Ţ[>_m92n8{<+1tb v.Oǐpjֹ]A㲢R.+cd+ /ޒ8juJK)|";Ր2tŵiI+M1Ȳe"r`29 -Q86TQ\ }Y{N,kkbͩ;$ݏ4Pp]q \S8裛DT 9R}%;|ܶ}# UBx$f0ܸ[?iq{],xW1FPǑOXM^rа`P>oxO?FfXSMxFlϥ0p'|ˀ.QZ# Z/wXd1+iCg4+g\/!Ƃ{~LDD:4By|n⛦zCMy:{ .--cuAg&(G\WEGplIPꁝW֩_ c ʍ "bGM ]CUzje^!* J̮3'22Xuf >`?o+Ti VK6>/_' qx}9s me͖Y?y zn{?vud.vA/l/8j[.+h6(yb̨;2z?} 8ǿ8Q[@E"[ Jx /r7Wb7A[-C6i#_7o^*`@4w|ނf/5^(.!1W^*r/#<}ƄNNm\J8wd8K{1o8 YNWu9(XNr'9r]ze\\o~/eA܇"`JN$=x.;i>Wl{AKLǿG]-eAz'((&rrVoBaΉč{eە4buQ3 ✃H=Äi@+7zѬ'k++gDk&5_-ڲ޹-/@qj>,WWᵑRoU$4~n Cu3{k 1`…7~r $-Z,,$jLWԾOZy#['YLL1pN6>lE J|k/H!}me";0*#a$5,d(Ff~!HUC6F豳 IA|KV(Xe-w}r֙un}MI,K"G#LP>8b>lЯ,H]%K9<`gxz)x1޺Pn eqsÿ+xth Wj@}bF(/Ffx9B}&8w_>Qy30 2&rf0zk%6 w6T^*~z&'SFS0Whl>F  ?~ =pgRbmzLyKzy v,HHj7ٽ/W*QU)+J){N;>~iĝKŜH׾ Wf`?nwg8p ']Y`\;a˜3v0u[OVAOOxk*<";y^߈L/Y,]o"j{>}0? 2Z[iļ|;xWm&OD fhO*'6V*\%~˹;3/l~:!9&\Qtq;7)*љ[hhΑ#죸'O];ؠAËQ|3qEE%}߶k߆|E>w{utj7ggA)⎿3'Uz@H룉HBqw1 "ak烏Z+5bAB]aYxm²wvOe?KxZ ~^'za!N,mw /6? *ܗf ㈤/Jѭ6!|h%X*Q%Dv:Ԉ]y|NCF׭J>I^|!ɴl˖hx͵/|a} z 8xŖ5P|"V:Kbm;&LpSC$ޯ<)f4Q|P~U1A@Vݍ z#/O;fqežI%6BIxMz&7O <`,*NouC9g>w2"튔6cFǧ7~ƳѠ {=VF':_~ `"x7"|+mOjorh!2aC }s E7»%P79LQ ]_;ڻpUi0W=ZXUB ~G$v?3SivD#Cq5t)tj:#鱰!ٟ+6K[ʌ6Փ$f'/e:w}P 4? M=aZ2v&{Y%Yːݓ!0BO1iZ]'#u“o͹Y>Bxwp!xFCڟڎ!=x `]8G9( SWclvjt3]~ 3h\R&^ SBI[˰\9ExF$2B.o9S`FbE_T;..TC4g^w P cC \W=zv{EH<Y\8An $$ɖ=*O15l $rIpd pMs߆7` TR(brzV(Q%'vnKf&t9 uO:.|"0 WpEK)畹 |`Z4M`dܾgx%ȕa-k}4Is܎m p5H'?P[Ӈ+-ICSyXl{jSwIu6b#fܵg&Zɶ^9 IR6lvU^Dm^5i49gňw9 aIP;]=weU*xSd{8 m _+ ok/^gS,C19/2MrOEX5C*UҙwR~\Bl"L껺(\sJ2~n,% ֪/WPUN%GmEn̅z0C-_m}BdCP7u6ˇcD7 c56UQ3?:c7$9Kn[FO߮Q0DzB?9Dm+b$ EKvE sPTwWzyqAWHarIC1( }tv{ꇡ[q{G=A]~~(V\_!,f6+să-=Zs$({]$8֟*KHGag|gϚټδP!{M}~|2p #JHoZtN1y ֜13*>KFܻ9AaE9\EޓJn?}f0taIɓO}PCKC(!Em(rY\8ա ?ڎ.+{xIڴ?oߖ{>&KބD~|CҨtʉɏmEAb̡|}%vǥXz1c+;Ugp#g M 3X侪P|ƐmNp(֛Eҹc%Rܓtd-/uØWA,dNQ.9u}ja01X.#$TVqNQ_ <>m:hNqa{+=,| yYh)]<`"z:=qjn5H2,zYYԺ󇗠 U$&;$n>gKwgJLږ"`Z$7d R1 ٖR Nr/LSbWIfCՃ*[Ű"'jG$ yȸ߼D`Đ*nL ~mn IJ \`hNSS_@ aS$y-;3Ct VT^)Ru 8訫'j[8or,ˀ\  ;nlksstA~$FrLM9Ì P"}U>`YF%ٸ8-+ BS!c7=ze7;G[UM"._l,.m`Ɍ h+%ډ 'TȴF3'>&q5ՄyRm3l*᝝'"{o++əo=J|a3ͯm(:'5::h~EBASARJN`]lp`CA^qvVԀ ~^Os!vS6VOX=)_:YРSHD+qMI+`-I #:; -)dB̕!pBXok&΁(!QWۘaaC F0;ġP h;P0UM~۟4 %KXD+y:47c-((.ˡpۊR`(8-0􄄾P"|2cNpsSvmqtX,wG-ݓFШ/+LX8 Er )'G%'Mm_rI] ϩX3{~ĈH\R| llA+=O I:}wv_ζTr` =[k =1CG X2vqHnUJtiCn;>JTG*K1{or8:aʱXA"ED'yʗ:n9CBr!k !vش?SX*p=MZr8's>9N$T$^ܮR"H:u17ny˦QPԸFbG0.QlV6>.U8&IlJh2"*t}/ۉSbMG֗f/9µ.icymr|6kS*!inZ)k\ȕs6}|M3} #P-<ϵ{kXt>S% >x qAR}& ZQ.aymT\<uzIDrB[~=ư޾{i;Ԝ֖ʌ[sJ}.UYB^rAk_;+%nc12.L{($YBOΒ#X& 񡯇 Sނ_ظen;7r%'G=cK? z<lR_HW:]c ĥlQ܈Yyx>#@fj׸HR= mjL5zp)\J@C0:7X?`I,CA8 /'"Kn'N62 ؖ[*š?;|D\: q_Lk׶yLX* h=9S[Ӧҁ۷.f'!j.S .tְV<έe Į.%f)¥|Lljšuj@ŽVK#B}N}FHf \w{Deݝ@;t [۶C8SY4!K:Ѹ-^O悲j~03cYIqt2k|S k7xߺQO铻;0W#* \13FG\qY(=K# mYJ }u@&5d cKV$f `g2B?]"cī_r]Q~I(˞i!kM]ALrR!ɨc$Ǖ#z+`OQ*#.FxŶ7bwYic=J; {ej_]/M[s*uIqbRޒᔰ0xhZ39v-?"Lے4"4Ij$=||__Y[_:'VM֢~pdC/KׂqB5tS2g-8MfC=gyBzd]]))b;Kĝ/m~h*ݼ-#whh畾#mϐ!Ks>O' lThM}"5~"=jf]5$ kvxtdsxIJ,{ڴabZuFnjQ=CCwdJyNvc=40lfUqqaA7kAeľ}@-iHy'UΘ&OAL(yjiGtjvBySoLE;Qb)% OWkpTs#-P''sl^ ix߷`T)əI i@evPI Ey{=Hף#=,QA0?mwLşƑC}ΓGC/ޘT"K Vf#.cH[ 6hJǢlˋoC8=n3%Cp7a#(`urʄkݜD EYAC/p`H3)(KT(Ij]tav(m3Y^ޝr{;4Q7$M B gG]ۂ$n\ _,HNm;=OG؞w c ڍ\{#~F{Urfpo&V. E")jJL g Mʠ'e`S>ĥyb-'}twאELGvm +Hcz>w6#`:s}Mfok(8n^yIMNlD-K7R:~yD\'J$h@k'I`Sw}~@)`6'>~I%i |7R1p9ZҶWҨ{fKs}Z{KڷaG><PXk0i![G'/3jo sbT^]z*n2x"x:x9vDpq#NG;ُ3Dzw=VU - hgJPkhS-%)eJcyY‚fѤƽsaekOix0uj*Mb:оbи'2&%zI *Z\vLsMi9<p,J Q ;ɆG Rɀ&Ѽ%3ė]BpJܚ-M<}<9NCMx.V(|5V@lxaQ_}8x&OmsOQV Q4[O:p jr79 Z>= I\P ss2<6\fugVC{>|'Ȭ~Xt.,5_m8uη:\`*Gr]c~Ώl.?MWC zP>A1sMcѦi=Y=i{~cv:?y{R@,(m7fA9kDiaa˝m r]O~b /ׂV(םܕP.wi7N$)#n;8ʂwdzbq+`h ㆊ$@f\˗NlZNVugǡf2` Sf[%u*17M ȡ{Q~M5UJiQJAD_NCm{$嶢M2QJMocq8SSˇ>#0L&͠Mjx٥8  Yuv^zvmCLɺBhXi9aWOoH:az'Mu@~ S*Fѓ I:g Nϗ,ߡ ǞS#saXOuPn='q ,kOjp4[:yD)&F l; OǛtI4={ ; KvV Cwg (%4 l%AYh уRu;~{i,g̈W!KC1PW*;8$NĺZMU/<\GYŶsf]hE&06=oUnMCݟ]oˏ fےbe&BH[ܐJOg֟A.rK7QwP3y7UL5# C:q{]Q|=^7V>~<"U^-Z jM^ Aӝ7Vj/P)]C!TCB/' =(l^MQW~f+rxzjy8&%f YsЊf>ѣ]m.u<)LwEVG_,TؿN{CFc =Mέrͯ.@xz _{jT8 _w6׻d*?O6M&v|<ܦ|u+`:pʸWl4OfWXiop_ LvX<'CVK2aכm(n1l޹&cDS[Dt%R]MY{xL7 ^x~'fOQQ8+*of"V8:ߞ+Ŧ;Wv/nynπtk9̫K D=96U0TXNjTӘ\G r:8j4V*-U2U=A(1߇"}P+u})qtQ;Uh-,>)zu4Yi'I59r3ʞw{ ޅF=| ,ꓜk<BE?a }MX6KR97] tYy'}Ύ 3U?}3hh:'q6cq7˪T(4VUz\G]a!kQN{8o:!"`*dJ2!1Q_(S^ʢ2"ڻ`!P(&λY> W1ܷE Z!WB^me{N f,7RҿjR8;uD4FrC'mH%*WvSu8JD rirytLf,F{GM%Xޝe6jgPD2OrI F;lo) } ӊ+n{qhŧ?)r> 1 -':nXc߆C>9St[WC<1ޮ*#=f?ūbi/ѼaOD&[hQ|7*__hK)-@ҿ:]`koXytjZ$ _xnZ 5jX=Mj'gX؇xȩ.N{.E.ŏSfa@ [D* Āˤo`;McMϰ ,\9š^3HZ(|3 [BE^ ?H?@/'.Wu{D7]%Kf՝F*݂8CZ+3WW(rb ar0EtYNg0"m-~3%9>2ap #Ѧƹ/Ia7#iyaN),B-?nvu,a43X7k}HO\g;y% Z%q\&ۊ5 `}i4*%J݁^5#*0p杣eϧLd6*j_[PC  =TD9nuLqF[Z"kfLJ/_C(c,:`(]\4,1320YD GXތ_:)V8O}ڇV(5]J~E\ )l\T'V (0E%\gWqw=nT_06k8tͣ;a#Zox7pdo{ZuKb#!\T S KC'W=vuO|F=à]',&&4M8Zu.R_PW),]<RF9Nq\Z ]aCг_;l³I?i4c8X`IDAT sU^@DϟT?#r \}X:7͐N<0116v' ga:f~G}^uۭgO|"l鬆g;N N#O<v,H. bީF.-,TKbvruۆ2+@h@ܕR;,]eu}i[Ģʰ_o C.B́ pO<̖=_JBkQO=K \oxMct$c>p}?:GO X[P;v6MQ[A=#k[sn2qPFuzg1Eq.GHW\§o4z4nrم0.cw( N n\\)(Ta„_VJ?w&vܥyfG$ IbG`s*5F;կ|x$o7`,wkЈ *j^~N8d#'Elמ~ԤűقQ ddL@g 9CoٔW*lHMWȥ ZVtkKV|} @'JAOp,)\0&"h:s%P|ZvK(noz?]=<@t8XGZFߋI2<4&}ߋ=TfS^xR#^湒D#9[| QGيR He!\QiOgf NϭC <.Ym80RV?߂Ia!r0 EFOVPo0p" \+w~%w$bJsI({p6mT ׃= <==Sg:x ƈh/aAW^apv&6w? WDvҕ2Cz,Ffx i1/øD]}J k=:PTwo (YQ @4?" @Hv(l3 pqO8~L]'f:O3iE97,&n^$ej:0cɌ1"zoJzh>HI9>iq`5v>V/1>3U<c!?!F"wB%4K74/r^br!R`,]"pvX'X<Cx CGDxbN%x&*7xjg3<'t> c#xمa^- /`63/apV b`3hG ˖2˭y35>fӅzϷ'CM~RԒ~!//Sd6H+ 0NAL|cZ% \HZ oz@0>}006~v$WiōgohlQHz;[?6# va@7\kSL A杦rPqa_(b'Ӓ4 ͫ6 uN zz℥n VhpJ"|}J@yg~c1Gj1NR/A;\OQ *COoydT~˂tߔ,V` ^_~\ ވw7>+HN>?;Dos8KкEzyFohq&:Hؓ>c Xo0J$L l3=n#w+;AHo6e3?x\_zt)ϽO^v:K#sv.ࠐi^9BeB,9ODM W}H+ o:Bm\qS6&%UQ55gO}[Q18w(C@>cvXSD4"kVqTY0F#(ᯚ0=‸ao\/c}u緪wd#fi\m̀Oƈ^ {S;/ro'VB|EN%P/ӒK ʈ+5I6#J0@oXD$>VVG5#*?<lD灸YH\D$#p@L^s8_PzgzwCet;O?YV^kLXc4KvEVx3,D\CuV3X;VH(OHH< g*:.!y6 *x{84gԳ?Y&-M_'r!oE#Fyg҇p_MAaPPpe?"lں!wT3Tit*\“֮؛K_/+a?9]80LNZXC8D=NCK\_b0^"u@)h8!28 GG_ '?4O*~D4@-ŰD,*"ӧզ;_Tg҆Ǜqç :ZXYΰ LӌVܽUȌ#jFft=G9Jĉә1cEh¼m@^TU^X 6Z_BK.ÂoXp+^E'1Z&]o\r٫KEg.cFA CX8CzR^$R ˒4nP )}*@Buog}, F,~]\jkڶ(*00(]/ޙNxD3-2WO|MF]EPʳbⶄx D1x:76ZQxg ˠK1 I+E~k)b]8?1k[6\AF+D9Om"aȈyd کfNq**OzElSsTz,Uڱ!NA.!@" H^Gֆ UU\!xI𽦆1zO \Zۭs!IqhxqqC!t2!y`pÒSر_qCE`Q1&%]a t7R0hXqa+M@ܑG9ELf!y sz*f+ \lZz$AohZ&Ful/eAq?ˏ_3Ioh0= k!!u GUy`xriGGN8܁lFT3]fbXx;"s`~|ӝ~`3Lk_Q{fh LVY+#ׁ& oX.o#,~O@[?f12l 5nC7/eT 5,)#'x2:)](Iގi vI`LW,jw.b-; ӧLm'"ȝ%>rQv*D 4:Po}xI* OpP%CKKx0_>$nя1qSO)-| @₄HubR c3`W|VrG-0BP`3:}0I(.K]_(ASNi!NCz/5-BodYp;x)D #Hq-Q6gDq$(av2"`Bu8F¯R׊@#ɠItRCDL&"CF`H>'KV-=1'F:3UYi D> U(4E@]!Ѫx_)Oץ*׃#I%{8>(M^!<*o\si. &mmbjG˒9pAxH?2{ʀ7u-%^I''h PlyH8xN Fq @ H̀3Ui,z,a}C/jɥQR`_2.(Ab^N2,ZU@S$=):%݂>C=<<6|5a>\7@VMkPña}(չA|pZ,HIQHEI#;љ;c G' w>2PQ#,?pp{[j =U&B(?\DZI[y@ n0(6n=|Ο@*W1R}C +/j1"^4Xfkbײ[Ͳ0([ZĭZfpTD^a(_~|u>`P D|K䴛alu6GbY).Rk9Ԏa:`X&"=7>Ms/a9"p9$BAspK:A h{²Wx࣬3gB&/u0^(0 DWuX~ʋG9$J`G+,j:3bO1`8Ch t @sACSn%i9C89JڡBR(qn=`uܠ5.הͨL);4t:=WMD R,3j 1i5V H5kBClmizja_fƶm/'glYz…Z<ݨ qIӉewDxg^e{97n޾W͜[^-"&77׵9Hp@KB \ά8v,muhq yhɒxc6oxhsO\(s"c/:DX^',M<Ϛթf҈Ĝ$5ޒУr:͸^o#Lԥ8~ނ;PIgԗ,r0㗹B3<ǤsD=4\Y( {-^Ö[Cս!] QQI!X!N7d X/C?p7ShKTZs;;JʦӋu+.Y!Z$, Nе97=$ # izd `̇+&0EjMgb?t\Fgzم'y%/b #陴/ް|a=2=Z:y0jH9B"CT#C-pWtr̓ ]tsv(Ώ_[$Wk2Pk?fQָLOq/Όm귝-ӣAan| +FR; bq7Ioռyi v:c$..nZ0-W)2C8**.?`-k|US+-axs: -".S4Eh}o@-!*FbΰS<;L~9*Nx?WA7⤓RoU3@ZsgOH>\O\ dsii!NڂA?ULMJY ]ʕ_殀FBr 2G`_~C<@Eʕ*G{pȫ0WJM˗VP0|i;dČvqu-C_y?92L4|ӟ_f0ta,6,d9wڰaY_ EP74B-:mAɏhKD~V9s#|E:O~]æXO#E| ܠc *V 3H0=ZV̈錪 ?X50PP RjŊZ-zՈ`)'i]XC ӫV)>@/iI# #eLUnjWÏ `~e܋Yt43?vUUS|DkVNp!:W޻C J$S>z' ;ЍG8ڪuql~T\0q\ވcLVoR7~ccp:<ݾ*UQx}oZi!^lY8m+݌yx_1Dw cGѺw޵If D)Vwc WD??U\;)ɖwYl.<u̺]W_VǎF;yeu+udp9,A ,CJ~^G04h\9X=Ua-F;鑼OTu,G&}nҢG̴\r KE똸sP4%y2rjn(qT54e{x.4&^=w !Y=Z9W>S3}3=M }SS(4)V^m[N WNk6$PbU3(,,`sET>,;&94cUrʛ]d)USx7)U`qa Ƨ\Uߍpk:-%7 u`KC<yT墦:.TY,~[Y./sWc?>QxmI_xP/(^ނtE!$RF=e!?aHdW/ y.<$ɯ@ ڨl)<@9wMNĦwq9*/l;y"3q p7mL탴̖ GuϞXӂDg9Hd˩?r8V8N`eV*Oi߾}?VK!dʉ*w|1Zee Qhm5MX3-:,-@솕`uqt"\pM7?zӔ)?VOc=-\>TqXP\[9QhRǜP,0y|f4)ywo%9.t$[^wꖭ~] <,1 "cn^ `TGnQ+W.7ǿ5asˋ/Uhd mhIAC GuôV@hyW 2rċk=PM0ˢ`cBG/|u0^/g,lP+@V*GFZSi=67OFi`8!*f91eFOz~4chpϤO3# _]}_[1h8"jԍ7פX  g|$,9GX/Ƈ(aTZ py_[6XR[R 1=;C_,]~aK[E e0~Q0O:a{z՟gb+l/x?XMp ^A+kLΆ+q 0t%[~Zui4"H<0>)OTm7Bm1(鯝q6r s-h:{ׁcNj/T7?t׾YE5%lw~]8^ N>V)@ݸopt?ꇑRLdDwV`VT$T2hMy?5@sRB.u߾>u]Ϩ]ƉmzAsWҴR\Fnc)0ò [㬹Y+W]v[ɯ9 L7 >Zg=xV)Z4ٕFk׏+XIL g֥wW5 uiKB;:A s\Q{~Gݧwaqc7VUhpmӪ3y p^ /yB4J%^+&qMں8/?;5ê^zf֩B R^aqvOnZ 7./֙N4 4[_X[ICqL&?HqsH_Pbg; Dςr4HX]ͰψQLѦO[0?`]a*"~Wq[A.妛AdD\B-x/zW˱nټe[ʹdUUkG#OW.>b[ Vjx ^_Yp&Q,m? /q'aDmIqy(T< 'mf؋{ꃆ>YҗmWlֵTW/T (g޴k-_2~tw g>B{'=R0َư1,~B<2ܱJG/APp xt0\f&lWQb?w`K&9 ۮ,}47s7yƽoK\c88e(# %/;'fh\= x-~{GB]S?z>|5a`vo쯘 hK ʐW@>"ǘ]nHhiјR{ AkDy-.FS>/N9mzȴ|5  w܃qV/@nXXNC|@uGt$0zTF T5>>c "0+|SF)]k@}\8!8Hgu `~n?h7\^ #ߐ/PL?:T|qq_wI69Iyď<{ԝb*z2P׷Efڸ9E|/<|$CHڑ+&C[>&Fz G4$E 2 gV<|}P݄R8Dx#Ȍ6jl|#v  Q<~4|9⃾I[g>-Uy1@U8]\rEG yQ8a8\1:z_r_.:қ5D!s*hagq-TpW~J]K΄4SDG`o/lq4Cn"\cE2%~W<?ժ b=E7_5pv{;dڰWw_弨_p^:R-|G ჾ@!|@u"H\Vv 5MlU4 |=F )yu R^i|b1hn&1Va얞mTD7;Zq'“<qP.e[`f1;*Ih^ڄ ߭5,/Ó=ŀ|- r[*m."U,$RP2)HP>X"+zA=;zCGs\ˮy:Z L_DhwƣsmYn_P>͎ؾ< IP풃Ir_U`WQ)v榯O;_JAwpϒbʴEQrVc"fD":#]$)q@)+S|@%!%5$pP<@tbM4޹NzpUK; ΃Oaewh:',7=x {Yc%y#&lo+\røJi$31kR̘t&d~. b1.p\YZޗ3+/g\1C̙W[ @'3g8a&sø?8 .B{ܽu/0"I  M4SXD+'}:zPQ8402oMCO%r }\w1nWEaG#S@W$Zt|3:IJ<њoBiSwJYP"zu!RxWW,2 &\qF5XXR D!6R籖kتG.b4[sϪ]5L9!;K +'y:я Xin{IF:w>tJLI|99YrRgä7t^qv_[٤0-؆ͫXn,)]wN}Җ0ybћqyKn8)rxO)Xy[|V=bVUhT| x#l]i` 0H[;u#>hG{5[ߛZV5޺~vƂ${-9֊yn~LO`iMg(4!['MrB}w1mڴ_v_U9K\zE \t)&NP*#;p!pmOFLz\icT7 ơ>hͤ=D[;zgKNSzV~nM;^}w@TľXa0o>sh۞[뢥٬ԋ <7]=Z1^rGN.ebWe QUOs=w~65w;|ꖘ-cn;j{7rfnkNg~q> eu)W߼$@;ntվoYosᐆ$Y^=o={ EU9]Y> ;',j:*`BVu1 9\Xg hp0htg29w40tǏb9Ĩpj,_E^* jxRR.h p[& V{47}!YsC?P[ULz:L tVm_uus )ad['eg%%%fRs mhnjLCPĈA:%E@d'gRGH8=D"8Ƌ3sRS  M~#P77œM Li 0? $WA ;@o'ML AoflbL FzD̥K 4@P('eQ..̢TMD((/9?%VŞ+ZA!Z`hb4J,q k$&h? F(Dubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/webstorm/0000775000000000000000000000000013013560574026521 5ustar ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/webstorm/WebStorm-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/webstorm/WebStorm-f0000664000000000000000000000012613013560574030430 0ustar 9aa3c7492528f64ee5435c58ba8fbf965dab8afb243287be7c09da68fdd35ba8 WebStorm-fake.tar.gz ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/webstorm/WebStorm-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/webstorm/WebStorm-f0000664000000000000000000002235613013560574030441 0ustar 8VzuP\ݶih@7ACwwowK4 @p I@w .!uOfޝw^M~U]:kgZӍ_ɝ^./_? !o+,??+ 0|>^VSuqg1 J[S=;*- oC`aY9Y?Fy}=s w^u g?hLOR&;'攂{;Tp&' LudVOɰ51BHpMhMۗӅ5<4,x%.= 9:F1haGY aaHe j[wG64dP=rl~.ֆ6ZTR- .r `/+H/qM'+-2 }ʵ^]uի,#3 Mk>C2ݨQzeq;Ϩ}k{p;ۤvAm'6qw9o=HW( x.qg$3{9 eX7fIc>xJz[:rW< ZB2}+ncpgSO⯺Y/]6+4>4 RK Rj):&K,Vdv˛Vtk\_]L˲ƌ1iTǻ@ Rzk̐SAQD\4rn"} j>g2D=^"i(,Mhݕ'["aҿ_+Ó3нF[%81~ldon^]i5eJuX=z)JytNگ)҇޹LCk4QB4.\~|?ͅ%>(QK wcQf9, 恥k;m,a lX.߆N2n^g`4)q&[DC-/? 4ͧ7+tb. k#p]g*h .<˾8 He0-SN+؄E$m "48h Q%&37{lBtk# ɾ`Ը`ΰ`lV6Wco0BX1qbS3XT%R4]+Msa|M{r׵]Sqи; Rpy0[0@wmBOLj@.|TߚTxNr nϾٮc⃢96`9!;w'oG@1mBW&NȐZT ㋾' W/;!?98.\ ou?c١Oe91q4 R~y1;W\eI}=-*5~ȴ]YFN k4mxPt@o>d9 28L}7\.M mOsEb@ )4z9ncġ£k1b^BU֏_JlZim 񡼇Ίz]^q1aݵҲiddZ]=$aXWI#$ 鸪g&p7E 2?FpT狣*q tv%Q6^b^I ( (o\eßnc69@|xn8 MJm)k%1q6$(H`hf/bO>qb|.]XD3ǞTaMw5̕ه X/WFLH~9U7>%t:|Lݸ1ƔU8ig~u~K#(BwZUg380|\ȉCt/C&C҈娪ToauFxϥDüژ*Cb{lؼi98V*Wc}uS[MF#}:GGw9Sp=k7w(Ee ‘@_R+Ӌ9\[ʮ^fЫF0t"[b7ʶgX+y 33IS_ ˾o @C~>QGYNDDG2]<Ix0,3Ŧ!3 mgvm }u9$4Й7jgW;5?& 澽ʏHd6ܓiٗ'22j6ADU K5q֫9w-jK=~KEG"=mRWmu]DEQ/J{SY*s*č$r94;_ &pQigdتOx~)> ޚC&cGDRRV]VczSSZޚ/bqsFb('T&d2>y>f@wL' g v1e&P"xbP<%n6Ǽptݽ'S;B6/$%)/;cڂ X!t\__]{hV wga$ p=0LN';8N>%Ģïˁӊ[.60v()K fLkIcorVʃgؿN A9OH 7uO*W\9M) ixVV+Ç~D,Dr[dŴ{Z% ex XzQĥIz{\jK`:Ew^x5j4@lS[iFg&*P$ZL`vj*P;'=pel_lT٭%^m~Ɏ2F˪^nW2`' ћM3=ȐXjK^{a/6~~TbȬDnWz}u| qn[$0Y׵m*`*!Ի>sN}jV)'#7.mgM̩/i6R[Kֺ5EN̈??8-?aDot~p}Zc,XbPka-[|c2 <]=h+H|9U s u(<|2Gȣ=y8Ef(:N pc>9j[rbxkO]bZј˔vi,egu[R;S뜗@"ۇ!x~Fܰ[(ħ58!oB7 !\CLI435At=9Y=L֕e5h]>9dh4;V<*S9#o GחLb|Ӱ}$(\|NvbWD*^_|r]|h+rԦaGo{]ATݩN\P6URंg  ^=]e~r`p%1<@lČћKss,4X6*nq?;ߴc;=Qv.|DWraVڻ{͸Σ7IL9O`3"i XY[^دb-OE6PO:{Ua[NB2sZ$б#X'mpĈ AQ*ziH]>7~bXϔ5q)xYo`JqZl򬞳4 = oLfM'EnJ _vUctpkCUx{@rN?;6ls԰HcsâMvp>uṓd˫^nmo!=qw)wynKH `|0}lH*B_/Fb=]qՋ~܋{xl-k40p|v^|֍RU9V |\aK a=B7ZfЪb[>٠j@ c$L0?u5WYNR͹=̲»wUCA6km) QU7AVg`gT7Xv(!Vбt*n뛍66 2>X*JEyGH *z|*QF\e@y4҂vl%Y.z#c< ScK:j)~bg wqC:"1*ynKK1lf$0l({- s֛ tr0`yz~uy!!hT܇2@EmDDDFU3Fa7|wHL«{.r-~PtE;?BV,u d~$kgנ-C֧Jt:|U/WdHL@dV𰳲Qd?~: >}o+-ۤr$t *Ҏo974'otFwjӚ7e  <2 a.0(H[ */$Fwօa20mip8=rC[} O[I_x vޮvyׯd=^nB0濓~l9ecI=C _ǣboduXtZ/0,$ ?} 5=ʀ'0 RG]|\L[J:y>adKomV]VCqsm"\$oqH X8|GMP(x5! {.-,9 .K>x:Xb>֐rƐVwkVI`~`J@ {+:1k錿+@]/A1h_ovvlRd*b|0;EkI,i^|']:Yٳ8OlY- Si|?{y}Yhk8|EjX@8(;]7k3!lsG m4<Ox~'1V~- CFIxIcSA`R2h /T=)-g k1;!f싧e0?@ W Dl/ُ>J7m;Vi Jp`BRw"a*)gԩOʖ_aOgcB}$@iQT|>ކA1s"޷V3 dIȺN# X_OLBAM±3v}$9jQIqb! qyʧ0~']B6{䁀2ABjp$?<\~pztaN5$2|t ubad#k݋FJ51€V&zildggD22VU?{!e pb3Q Ys/([MF' ULb 85\Mg3vj:@ zCeb@[37 -< S$ǞiJ5oWWvgZߢLTM3=rJO4g@d.YُZ1 `V|h .>QlnR#)&ƨoص(Ǣi }/jAOF{Ksl`Sȏ?tcXԙi`44E 6^Q3f R}6m2%!mHh`q9Eʝm\5=PߋeM6vd>*-͚.M"Px:ǞCPQ/;cJSTOM3՚7]9laѶB  FriPA\feLj͆ d,MbWJ LJd5:&o ]~ /wuu q[bDDF} U\N;r_ ir u0ygsgOmxDcS-eCo2M ۥ!'ʃknhMThynRZ-$`;l'&]!G''++Q78\ԊѡthnkubwTaXA,۔*q߽aӵˤCp {X(n#z:m r}ցE`x~_L4 slQӋNϏbF$S&-TB`*.x竮gsӛ t;jOujlk!2%9rm6‘eS E*7%zR:ԃݣJ'x6^?F>w2}sF&6/N1gv`Vn.J|k. x!?frL>U:RByquS%*7 *ynbKJr( Ni#O(,ѽoA5=>`/%,>w1߼P:ح:r-NZ i+79zi.O'G[Kh_[o!7%ߣ"9F/A؀<@BMYKFPgK  xxx?̿ݟ oxyx`{_zڿ刏jg&ă__'_H+WW/_@o  }U{ǧq`?V 7ןNAw)Wfcbw3y}¿oK+6ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/cpp/0000775000000000000000000000000013013560574025441 5ustar ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/cpp/clion-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/cpp/clion-fake.tar.0000664000000000000000000000012413013560574030234 0ustar 4588dc2aab11ce09672cb5d7516af0b62cf0512d62dcaaebe55943626c444871 clion-fake.tar.gz ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/cpp/clion-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/cpp/clion-fake.tar.0000664000000000000000000002400013013560574030233 0ustar clion-42.1111/0000775000175000017500000000000012470610672013164 5ustar didrocksdidrocksclion-42.1111/bin/0000775000175000017500000000000012622560702013731 5ustar didrocksdidrocksclion-42.1111/bin/clion.sh0000755000175000017500000000043512622560645015402 0ustar didrocksdidrocks#!/bin/sh # # --------------------------------------------------------------------- # CLion fake startup script. # --------------------------------------------------------------------- # $(dirname $0)/java-fake returncode=$? [ $returncode -eq 143 ] && returnchode=0 exit $returnchode clion-42.1111/bin/clion.svg0000664000175000017500000000000012622560702015544 0ustar didrocksdidrocksclion-42.1111/bin/java-fake0000744000175000017500000000002412365411414015473 0ustar didrocksdidrocks#!/bin/sh sleep 60 ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/0000775000000000000000000000000013013560574025561 5ustar ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/idea-ultimate-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/idea-ultimate-0000664000000000000000000031374713013560574030324 0ustar Tv֖.XS{DCѺډ4-Q6Twu JI%sWՓ~~u>ӏ2?.|œjW4Eq8&JV8d,;qWk/C(&4{ `@Cg+:Y}Ye-pS?5t69'xbys1>8$Y,B`4dIKpX-bh2YD e_:p)eA3j>ЉBxMO\c&'NycWcn<{׍ N7|uk(PX~"ˇd7O~!8e?q΃b .gy2^a:Yͧo`0P ndП5W6#.Ygaݼ<8{Ygd& >lz?^@l??T=*g\g~ļD !;H0}<`*"+c']02ZtK'2 mMZy~Qfx!2 ɀ- 1rXMP@[1r" ",,MmevdVr?[t4 tXn0a,٣a4t^΂y>&'p yDI>d Ȑwa4MY&^-A<_ၙȎe3MP2ʖsh.xǣl7e{0Q:<]=| /ܝixŒbÇڍ[|z8}txH )EM@6آI^)/գOvgb+d6u\a=k1Ȉ'hσ??6_ܰ'˗=ʚ2[ ͓@Hel H˜?'ufhF it›*ShL&U?_}/- :IPM^  i$LRh%W!g#7\z!PZG"E~iԛ^MZ&19#hbm ~$:T,p+ gR~dWV %~p^k ]@RXV{bPG /Zk]21B JUN(ȑ?fͻm3=? \k0c R?cd?M"8hgܧ0P2݂g~~zqޞ<::h~/wG\-j0zX{@ qZHǙ|X8b&kV<M/J5f<<&]8&WdGGG~,>6C/^¬kMᅒV9}B X +9:<:,>cTv^~Glto=nw}ϧ nQߢߚ|}_$tg闗[y|/hy $zBA*HU'r5+Da:9OSR@~?)u#IJsa()' }`VKށb{j&S:!it0Y%}8f3JƔwpb.(__ ||;7LSx/ ^qEo` Q}=+wԌc7uj:Ԧ& truRL5ۦ$=_MhJ4%;$V5{/0D4Sd2: ]N~ye76 EOG"eBUrI y?0,.dM;eU,=u9G98[!K70  GI*mNMe[I2JᄥkF7zɓlcz )#x78,hPCt"ߴֹaMǭ~i2~|c͐@xaYBÌm^&đ,s53=ԄI]S*dngV?k Aw AGQȃ,(ODx|Mm&΄P k5(9Q.S9Q;GMŞjyMmF-2*0BB6f8♀Rac*xW# g38 $>eAq^@\嬌EWA:f<ÄI@3cҳZrAˆ&+TRC70g+,%C,Ʌ,w96͈CҺ0A\a83UR!ӧ 3ˊnIr2rvi]H d~ :l*n_K̃hQ xԴjM,7p~51"08rѳE]whX}b(|ϰL-\ÅeYjg2JJGNU욌yXpW` ` *0L{\VeZshUA)hNmZV< @<$ |Z& ji$Šs RW2}o|1@>/6NAoVsOAiPJudۙ?[:6~q lrsrmX.a댺a _jx>bҲ\uDuz-e t"*|5-+-ͬ2C0K_*\S3tIUvi ('Ow m xO,;AGnwigxmu);lep+COi,4*j)n hL!>I8D+z>ZܵRoaEH#% GXZɢثNi|ׁכkZ;WSm읶b-Z;;kx-yfjK~DSҮÚҿO;0?KC F=䢞! l. {OϨ_h_|ڠ7_a)f'؝aowz?^7 =u޶NKD/%`c+S|O6hܓZ>l~n gTEuZQzJ4woZaeʤEFC m>:=9E8Rٹ$Ѩ93_N5/aGFtsyFmcCK*(p1 12n#-W_Qp=!vNh9D , yeтژHr$7CWaqi H8/P ┌ eXLBnI?UeTD2K>>mv $L}Jo$~(:!xԉɍZ2,S̑j2 WI`1Gb*b5duH$s"r/D_0- Ëبptm `CXG4JȂq2ҕOr/89t +PӐ*8ڋ+DHKb%Zڼb$7R%u1bh8[}C 喁[/Cg~ @aݜEh L +DxzOu8]E*SDwTŒanz7g%,&hC@=krmr&j]J}2#7ޤ y&b0Y( 'j0%OvHwF chy H/ FEU7l*$,J~b$fJtE/ pp^}-Y֕}!; .LQAdQo+}5Wp쿬iM$4tНQ(r`$P eFn8b BJeaC%8[)|æ6Q"?9TV!^S,LY#Vs*?h , y23t=FÜxd5,wxzr.K6'3/^̱Tnn"q4Ne 0EPY+MECp_po 4;LApeJF4PQub)`AZ)G=L|w||=hvpy]sZt҈g$Y|I{G{Gq*5!T8 &  S bh2ʛ ?5\*$ "mqܡ@+20h6GR/v{)RKkY:[0s1WAPsx̏DDL _} Dci I3ˑVLÛCS\[tyBq;a1(QԈE]:ā;|8}s#ED\.XA]٠lF$W;-8#86Qd GgKYE|ľ (]˫|A\%SH] c7-E Z6vLDٽbBH; C0NGxuG2&ǸLDL;y6\X*9^DCp;}/׭P(ms_ަ O*h<@vpovށa(d:OnB @Ol.<`% N F'菈\vn*"W؆sA8 b-u5B]MPWS)WS)T­)~b tK)mlߩK)rC={hKGUZ\j J}q/)9?khI- C%Tǔ"\0V _W{6C,k#D)EXajl l $UVZJ`{5ְVjJ:o1fxVk|>ȴ­RFyyz,Nk ÀTYo||0\/sDk'zTDkhq5NƉ8'Dϟs !%Z|~~CH>SބdI[Fׁh84p*)mj+P*nWa NX}cN28Ja\2\kaZ&bpkkqo5v΍N̄+spʏ˗U l|> y.^\WgQ[8epfi$ɦ)ec}]tbQ5kc bA51 Xkc bA51 Xkc bA51 Xkc bA51 Xkc b|= (K?-_P"WՈ?lM43ɋ nh(Ov t+4ZMЖz灢U 'tbKt\[-( <2 P({Vc&119m}bJgM\Y89|\j4\p;nc7t12"&n=$М8<o"a$')nsf$-QXfA= ,e{䰳 :(ErdVP:+MՐU<0vzaaZ+ŽVnR%"vJ6Ju䘕+2n ט&h{AEkY*=?%&V6[@uY1[W@>u_%"Bǒku\LRc0&GE_jWD=k )Np=ĖV.ڃNT<˝f0B2 JmR#m=Ah4+5l[&nkup]DP/s{vɢ)Ir6ag0E-E^1SEbf= bhg7ʓ-&2pzːj"oa$ J,槜9ʓ V@Vm6SiUWiZR\@JYPEC$]ա""ᴐCZ?J~B*Ő{x#{H ws9'nUNk@@}*L\&JD(*T.%-@kN3#zN9i,.F\ *B 0en 0vEAY#” fB a`B_vOh6x c\$+`V)Nx4 ? lSB$=;? i+nfv}2I%DOwʃ4: BҒ@Kq8A* 0Zla˱i눕M* #m̠63 r>7.k :Lٕuݤ㲻αz%z&/Kl\];^ NЊne\Fԃ{'0⡂,Cg ļug|a ]:̴g]S_L9rȍ| obIՍ#*lJK FjD>/GuY'EgPx7sM ń$Sn]hK`:SiIO.D7\=Fy؛/.d,FQCeN?H%dBQ+x%or9{.Z5w>Bp]nUrKe 1b@`0-{]M>23%EJzB?/8`AuM"_h8I@Wo7`z{ PdE_w޶c~9Avp_oZoۼCo?}6Qk~3<6jxM6h05"~X/2H/@ߋ@w>̴ԯk侀"'AKkSN=z'";8ofFkNovXK"FN m?|>Ba5Lo2L"^W"i ܨ `sYY]Au\4O*`_k 5?Yw|x\?;<_P6XWsW%y,nY10zN$-,!` *#DepzoAsLKŧ% 2+c갻A<VwRiq"F7SI&1ʴyHbҽHV4:շXE5s̅ ES⳵= _Jp"\95t.݃+nULM<f}|mr ʖI3Ac.>AkPKW]R,]Y:$4\bYkJKq)JEyup*&'ˊ') $KE`<Ӂl /^0}eci6w۷AB4hB'jlDe0c42#5//.ZX6DjJ!6BjQU U0(|!u@DU8 @_YxPB2"8=1rCquCr_0`r =eJgȌa{ -"E׍B z#h)hd\˕BqV]S.uR7^7nY*hKԥRA_TP]*.*]]*TVکˊ|I>CTTF9*]EMRHu)~U)r'I O66U>s>y'\"#WVNl*.[&"RPDgof0:D G =xrQu"_Z$rnx/^y@}Z7=Ӟa[nuN8Zb=%ѻ7Ѱ2'uٓ?F-DR?VKԥG#KեG#kȟӺH]z.=RKԥG#u鑺?ex w;;z<;8_#3&&-^*n^狹'@XKPs$4:tF*WS^‘65T5`wI `x-qhSxs`aPYCE4z6hp.u29%;Nr-(`=/V(PSkfݑ$Qlb. _u.W6 ea 'бΈ?C"81gJX G!~Q9v ߆!E wf\-wjA|׮&I@qh"*_T},=c8c~{t5>?;&![2 3Lu9C6i8ZJhP%nl:PJХRrP*;; kDsS`E'ڃò1dzwYX޽&I}MmBKBy=U?YB3Bfm6d-7?;,>i.vۉyTX `sGҩWUZ1IsU 2mhoes!wҹ@k qQxbE=BܭB8=/)Sm։Q;̆$UQ)չƥ>`&P|e\[\SܹOn1#S-T#mzG\Ϟe(rM X =dh^md4j?o*yvSȪxp^ɳp>dBeN({z+>r!5Ψ|1HQ Bi%ϩ4 aڸ<` tR/f4dծEWp,NkiiUBfӢĩ&)X"%Fn6*AUV2n jH21g" yhfhe\VJ!'R{T>l1jvŽ)Ҝ-.X:5uW߸ [Wɸ`.!+[zhzY@@- ?M<_tժi;݉UTKDΠ`ro$amuG-Nkq$ ˛Yuz\e9HjL8CGDtR>*HSAbӂT}ȲqzPaRf4>VUa Nib, 9Мt&{S@vq#$jҔ&nV*=.84JLx̩LF&;w{и.ӫgD\Evkf`TUe5r)tnj_Ie/arU$Yj7Ui%E*Q&aA -KǦaoT唝+{ *BoК؝p`D,~3AdUyrk+q*诌ӏ~UL$p:/ѕr錯QVT+ӝ2}?Yr*tw$^*ҀYÙETbVÂAmJZSF@x6[`HW@NGqri h߮ `߶`e\c+d 7FbL<#{~}`kO ;ӢfV,AD{l3o;iTz@sDXvb v=hVss1#JIP셓$*kUI"UYrwKUz;ew;/~?F踌x#Ā؈!. nرUsg l??Ijk۳:6_R7CvjaNo8G:vJ^pKN8gơ/ YcpDhs'̊f=uR.Y,ANLs<VcBˋ%-΂Œ˝ es{{ ՛.+Gs"{Ap.*i Tg;!rl7Br¡*nC Pl$"Xlzoi(rʼnX4?Jl.sL 7%օ%q}Gm۽0Ys{5U:E MW]t5L!FaO.!m\F g[m% }u>~_ CO/!>;7dy,.f¢,ޣ` XG= ^o\I"-8D2pcj^<1y0{\iayayAyhƀsj(Hާ;?XŏS(w~\Fh? -7tF^.b2RKaM7D*}k$^w1nLiGJ`+eM 1Fpv^+8.iVCBm+0oԟS㔼q*mAt=i V_xf,LRM2\b!gHbiI]#Zg"zU=ڒVdq*^ڐxnNLi')@(3GPʠ&M@^hZE|m=NUjhA*lSB>ݦ<#ukfA]fZĴ&7Tm,IX/ږ 3~-}9 :ŕ2j̐њ jiP,ZI~TW-ѧ8Fy若C<s&u@ gN<>c Ji AeG ܋K ? ִ%S@x-R9iK'QL #bk4{@/s-:Y˖g;Uj';YG8LvǬ©d[E >@f/-k|6%?w*1@z `:DT K.D aԺE>MҘ58:a^e~9 |Vʥe10FOp*Mc7px#\iǎ`BBaHA|ouXHŎπ>Vz J=l̽ˡZJxm-}֡ P^6Wl;[Ms-1'G:[AP24ia+*ȕ{ٶYyy-S2V`xo XnT>d"!Os1ߞan"qweQyό$8ELvBB:Efp+BOHF BmEZ7,6Pڔ eU`KQ#3IڲMd0>L7y *+67]WR"2].@G_;!ܫ8xLBQ2*[pFН>.B(/ycFANWkGYe>W3+SZD'\`.MTg(]P(v7 J"%NgC"bΔ9\BK| '؝PgS%@-O BhI㮪%fL+ *_2@ cCy"iw)vcXxԄߛJ;8jLJm I'~M0w\ ιsMmӎQֵ&\`>#b% 2)cTN:ʕVUHUiQ18ߑ;< Ȭ9f@L9YEZ0ܜ\Yib+f]ԶꫭC&Zˎ1v]9dǍQюB:iJXʖg=8M&%q{X=snIC͖ 񊓳:h,ұ!ݰ5hnK2EiXth\>ir! US.9h:{24}Yi!щl* ,c8X<1^ RXS`vhg&".A*F^0AɉT@[(Ř:gFh5R´VʠwL`@Om?N7"WY?5;/և#u*3P Lٵ[t*;I!_R)6sL_ ,Wf!uWĒݠFU4y[S& C ;ڛNdž;stY0ZOa3?hV4D!'|]Q4E1ff̟y2ijm(wHU΃t1u88DTu ֔0D6^a&0k[-Q 48uqt~~[H.?Vh(:_hHMPju&]by%[Җ, !Pֿf|iVĤ*,XM4UO:RApq(Vlj-ԁP2y'yFi*.N2^.R3u]Zkk&3|q Gk[ ^J~aE:/+=cA:ƈ5 &>yN!&RT@\"O+f<BzG ԝ(&Gܑ-/a1~}WH8 2HSv c%I@1PàfMB |#͛Rw»nҍRR Z-UTǔvӏ!?5XK` e`,C5XK`,a5XK`,Q%jD 5XK`,Q%jV 5XK`,Q%jD 5XK`,!K`,A,Q%K]7A'ݛb?{X*y矶߶ 1v4S_oWQDZ&"Tu5 vn}%*bQnjx/sbL﫼#4ו!sz&z&l}423{F?ā(Uʭ[;wNl9'dL6YT+̚pde͉:oyÌوl#+غW""'4uOAMVjYNYżyG`wHٔ88ـ;SCQamx)5}KMkq8"}{==R6oxžL3ex7:XNgՔ`cqdSfEk1;x03άr?_0=<l@ǃ;B>LLHU~P!`e:jNY)QǶ+Fc""N^Иw~#T81. %49;+071l4Sp]tb@UI%H&PFB"r|B_qXW VdW+0+`DJ#PX3&`Dt̼FKӊUtpc)Q( 6f!J2F"F0>4KQ {5 6k"0+ʦP"dKNP:[ȍA/[аERJWi(!*WAV|C]* 8PɷGv.P-C xG5,CltDuڔz FGE@S7p+N3G@} s°FHDp$9xZ,=?hqdƩ &y1Tpݩ9!,,fIE ɵW:*8y\U\ +Je>L4 srɒRZLl)hx*1(GÍk r-&$}GPS]O8xl| 3e:ZXԲs6IH"I|qB4]:@-D!*vJ9z@qV<hVG8 N`d-  ԗ^S=NxЙ' pbIWF\\ ;Z粐h ,.nCtއj|im;B_}Euǡ(1?l먉x' %gi;-"Un[ yP,~ϹP$lBߤ- ^@|QG<rGzŰ?Nx:3e :k.DNqg6 66vJ tvL.OL[A?x6UKy&d6N>-9]ƨ 4:Q]Pos殦&`~Y+U݄wI瞠vX.6254#lZ^x\')3/Lj7,Ahlue,k: dTph*{(GZCr5F6a+T=!LMŇM#SLd4f9۳c|NTP:yOEW * YY+.ƺr[Aө5`[Pa Oy{’K~;mڧ6~g_ o;e^Td,I nFr~F?_ !4n ?vz'Ni9Z\yi~Հ6z>k6 ag*`8 FkR7mt?lG}_/[+ҋ=oNMcyMҔ%o;N%o؀tzQUɮzOK}qkc^etÑڛ^v5xۃڂApz`ЦMjrFܣBuVu T0_5L}1 HAyGTC_*UоV4tX dB\GSV[6{ jtVH8%o)jHƈ"!obM5֚7t)D yT:cEdP;T-ځ6e8JKOʦ!|Tj!MFS 7E7HrȊkUe.#̿h ^Uʑ(xZ4Jd0-Q+"ޯ\ɮ,>!hQИbUئ#"ߠ#)_H*qN2QAzTDkDԹ,sЅ(էցP]"̚ds4sȳk;4 n!C4JVeJ2T^_BRe+Q]ԃviJQe ,Q` B YKME {̣|mgY֙}2|JhCFw\g7KZ@ H %H|8BϸLS=h.o$Am}n; - rIv7nE~Z7}C'i]a%?˓7%AzզeQ'!,ϙ4 ^g@ )0F@uͫڰ[*Np~ŀJ^:]]?/.\K^H;ou.{r{LW]9Θ!. CX^M TWmaTij;LOzR*OZFկw rn ́!wz?^Hy쎐skC fyD)nho16 O;'D<8;iuHS&hd#UymL;MVCҠy6&,kP `(ײ[ rQ.9 Xxѷ4Ϛ&ʪ};$]5[Nz|u};;5W诎Wq 2o\I@ eA1lrRW*Wr "bI)o WYRx)kX ZbOuHu.wD MU`Dv[vRt`_j=D*sɌt~K4p$YXV0 yW;I*9EgkcՂ, /4ʦ;z̤Qhʱ¿aj*i͎]VgTvqz29Yeep.I*m鵅U@U7[Do~Y _ C)l:J SϊkACgaȿNZ #57GtSDO0%bC^i79篓dqx|-[i2@^BYu+O)d10zcu-DSd.sqTpiJq[NMÊ )re9aX)b+"O5͌뎉픤'*-ĩB54{|۸P$KW"ro*vRl~.YyV Бyjl0hM.+B8 }cdc(ĝ<0GoSxӲf)n4NQȥD9HBڵnp`x= t!{[S2,gn v  )^th%*g ذqVfp3PN%sJZ#V7'λ3΢a.x4T\+J14}=K/K}uVw8?:6?{_?OF/y+'O<9@OڽG2~Qc]}7/бfRp[_}A`qdo݇Vj/nZj^J(:!n!ޟE}>[X߾?<huʛVuý}^ /8IyƻCh%hUr a , ?:'+uQZb-e{?Yb?OIlp4jZv3K9F$I\OZe~ݢ/=`:u>`vW{9y}ԙl 9ç=uQ8A9ip;y4=z0:H-1#zGBj:ϲix.zFyٻڱA n㭠1B#\kq9sK罭IkW̮b}Oan( A4uxmS)0DF0Q6NVᠤ+T4k('ydrjS2I 6\TwuG7c.&yMg*(,ǥ`RN-#;0)Gfv>h vu`ӶدlL><^Ij!6ӆ7W%RV_/2UeȦG'eU^+N6?NN7OrvJSS3Iët{5n^gtyczȰdTF$ ި ̚l(Ry&>BjVps"äyB{`򾘏^XbwgNs\nY[VI?-Oܲ8f(-bŪS-@6Xnx*z˂ac%| ]Jq22ч{(r$;mZxh='(..1Ȍ)h*W[Spۙ>ˠC'Fphyk^_8ϞbdŧM烎!_2ty؝sYbW{/qa@|zCT%@OyUJk̈́ڪ4pBBQʅE3L<˔;#Ow))vk?:B ,uT Lz+|k7&,c&fŦY.gڏ ;bvʳh y\2eo%Y C0.rZd5hN~x 3J;x9{ IrGx)?d=_Q?r> ^(~~ntVaVsx6fcm]O3%(TݦoZ 00̳/*{xܓ ,6*9a-~LO"Ŷ>La <765w,;sMCdU8M{/o{d:5!# T:쏼)ʥ$w%A>bfJnӔcߪ 4pxw]f nۡWT#a ;ˢ{=m L ~;jn.q< {hB'Bq5}^淥bOn--ܟ+$sSVTQ +(> ‘wwVyox`Ao_ƊTaOI/ӓ3Jxb!$yN5spj %uJbp_hEvb6lu]'*t4jqE<:WB] A5Yt; T)qcz4hV- >""Q7ՓFm[ׇٮد8| βZ7Gt&9[^ ?eAAHTWPb)ӪtSN'|z{@Q)_Oy4 꺇!Bn|(>eadÇ|OvMV='SFyhtti I>Z!7G'@c&;m:%vs}8Wщk莹.\=" ՠM,YnÔK^y ]ZSŚSq6%r)VCItA1ľOJ]7쨘eQUkZEJCk%$%HI- M/=@a>u 6?CQ$#B0hڥ|q' IPl M$]+KDum;p'4[eӿ!/=5 ]SLOv7CcXc*[V} C@\)ivvyz2%[?>% 5n^~jY[\o|k^G4tNMсRu+R|di`-gյkc'XDЈ T͖Dmզ#Жfg8 {P-8D7<Ob.mRN!4 6P\l뫷(2O:V13a1# Y Ih:Z ߝ ?{.UYǁʼnY%-g u]T㫂D&Ǩ2`3vc >:ޥ" LZXB:70`gڥ6d4iU"Te_J}vI  a6K5!CڣH y3a>>"gpcCy |b\FLؼ@it+8<Qk6 8wY4yqtܫ\S㷸mn`c^!H2Bh."B/+G,Q+^fw n\{˭# DH c[x ~,Uvnkw D\E=UUą7pL&]KШK QݝSN}*#Y4D+F@YJrp8?P{ahK*&܏.bAޘ1onOޱ WWiZ>5häTn3Ap4>==;!iot9yH ]5ò.M\5qb%bSFkI7}(z殽7:uN;~_a 99+S0$2rұw&jQV4筆Z4B ^`" ŀ]> 8.%̈&s G;ꂲͅgR#A G̓Aż6`T0owЦe\F,O9U6V)pφo>$ =QcV_yo^{3nVZ=1Eˌ=hhV!lٵlFXW>ˍsd @t!g]@?Lk ؽVp?D~c Ay#F(j9ti=`-AQM4x1ju DmL>)@3AJP(mM4D(,9_ɐ)-g:^Oo9$@ԋo^{!܎l;f"4Z;.r|Uj2Rb4_bdq zջX WSNY\5q1)2E3Q@$_*StX.S!z}b7s9m0}2\3+n)L5!0U+O㳞uf4cQ7q*\W0-km YRiAܢ\F)R-K4*"rzSJOU *TԔhOf7 9vTixa꯳+Va̹b (19r'@#w/⧊C3\wp1a)qjRN 9 6>C+tLWOL Wq-0`i_DL7b8G?ZE1FIN{;#3IFB~}Ԩ.nU'v;282]I4Y1Vsl>ֿi=QWKh6P1'`Gax?(;W\/D -uhN찊5-j4v^UٿX\߈wf\md&┹9mBp'Ț_UW1åVw̠(6Ҷák,F3ѳPr)ec*7Ǵ?x0mIǬhłlRżog?x3Cd0H0_=@9B'џcYUN7m;Ḉ7` N@y~Ꮼ2J .}t~ Q2i N 0'p5o#*)R,Ԉq'qa$ϷNa(ނkoqyek?㌒lxuD|gDoBo~a<(Dв]IdR *TI {!z|9\brQʂB[hZh m;s q nZ=eA)RI62NPVݏ#ms\7W Lo9BF#2%W 1er)ib&YvI"lMކ d `•}ndzu&+6GJb鹵#107f:*/j#_A_`( hS^mos!ɲ vB=3w ٗt恿`{>+2_'ez#ڥ$EnCРr#"CI#\D$>l"`kDv+鮊)lnW]4M]) eSWmlTN.9.늡?S-m_˞vL Qろ$@x^vy}_Ч䓠-YP3\}et~L"B3MhUiU=b)rG'GGw }"p[S0̳{ ^p"< LGYw}ɉPS9ۺe≄!N GAL*.=;!(*ߜ7}45!'~dG|+=ӈ_; p/,4 +I08}C֝'Ƿdz PQKODpR#UUq2_5&c&"%*Ě>Ec[/^v(ImÍN++'ޅ`[O7V͇4"Z`SU2keDZ+fR餝=|'PR%mfNI~[J/YvipKSLnxm:\(yi=[Yt<8\}ȏQ؜jgI\ˬeE}тJ5-AF?=نzZdݜh]j qI%bpwG9ڒ@Xb)zJA;Y$f:Sr>KTyWM9,HtsWhޯ(`P|tOO|cC]hLhWUcլ}a?!AX_T]VQ }-\WX٥/]Kxɋ'YW٣>ĜJx3IɷJ_W>C8f37/1P^:iI晙Ҁ9`,"1 %}]v'SkRfB㧔- rL d[VR^hp"~ePL8@K8Yۘt{"@_21y;]Dt}ZO;޸]fvm:'ԫt0[*eQo $|&[ 9q7a>F0ْZԓ"`'BݟV09 |T@ԎFפhh4י^Q7X C! .1]_<< ?ME_Ơ:$|rB(u[z+b`IK8$Xrya3!2IH̹bJ-OgpEo8QV"qP6ҹ`HIS CI)2px 2s:c2+18a6cXi@>UĕL9W[y21?-OrG's(J![:ec]W׷b k(BHFtnr:?R#PG7=oGf=;ū;h2@$S(F ^\S'VtUz;]-0@ª뽺 uyC;4(G5`*όO( EUf-k}5+NߩZy[CObnىm`IRt㐕1uQԠc?呒f :(1Á/z}bP+[-UNnCh]Ih7]l= #4rwW'jٓP٬"^ ,F GlZn1DSq;\||[swOaK6]}ML6^ N@?P\,qbXVY Nɀ292E6EXOYv_4+3:ו3;6ϐ.譻\it^z< úB֮n+L]{dpb){ %yW\p1;](Sx~QZu_vX/׷ڲ]TTDjI7> ܥ$k@%+)~e Ir33HLBtJ ieI CГ7|<$: 4No?M1y 'qЅ-'JRCncB!w%GK h=]N|gDs^!RB>Er/qWun7zaIC:a' iujBA g7#ћTQxLCJA'P9aHl8tlp“ؚϋ%h|hNZm  Un ǵޕ@/:ʖM'З@E) "g7+(\,PJřM/Ӎ.LWpvHZw <[ZC.)U"DNqUwA]@>(b0A / ŷYZRl[+ZyapmEp*[ED+7aekAuueǫ8 0VD]WTrjYR?'@j Oܤ46j]#Tn? *@dbqp-<2 z!̯]QE(˾XB CDc/; X9[,F%0(֚.py;*ZGjphT H SwrsAM4E7d~h3ӧ% *r.A { o\4|9bIqn)m*b 1 . w8ή3BhB{c&0gr(ેwM#T lQÑTX:=Pi蒀ok"^Ls B"c͌ۮ؛c[V\)uࣳ%,t<}Y57ғgvn{ BwfD9L}Ạ`b#mJRe&֪r 4`  T aBa^ޚ]I =u4⿦l3J p6z~9I-(p-qP#%A%q+@tv B's K+xMYgE]gs6j #47rVfvNl6.WSv|y4hbr˄ߦ_+ME3o9~}E`&W6vCoA<;lu;aDXVzJ1,@ 8%U"PMSFDϋI3E%YU`٪Lh,hB bQ#4u^C?+OF[|o BCpiO"R$Xqq-K#|a84 lrv9HN摻D5CSD9RSMdU1t9s<@ao4D3\6Y|cAA#2Xo NnMv ,4vo46$"tcz= Ww#V.aK 1EQtכ",4JdDZ" FNWZ1+u2muryW.YLo">g\'Ow0whAi%A5 $5cDJ;Erk=ZnpJiN;R׿;:P2E8QpE ƤBZx*=2!*@41_vBBAl; lxҶ 6-l4H"}'! æ|xwDQ|Q7f@JA( voĢiYOӇpz1"P)Cs5~L=~=O"DGwvʣģ38hC^/ɾ;K=MˈMF3 O5|^88wtpt?P9(qRL9 9,7YE4KY bmu_K֤Eʛȿ|E|*tsj"U9W҂BGTqzbJ=.?VBv-l}Wv^鳔JGa"IY'3}n%D|9Q]o6Fs͠.ȰaE5$bG 3ĩGpws0((+̞6X3)#ߐ9ih|UdGɵudu_)85bbݦku!t3 ?Օ"73J_ ߑvJ y ݮ_Q5\%M5h ɒOe[(M3 mMدTS =֊t,#&d[%'ERi_e1Qp"?`R$JlRb.v1HI+ LQ8Bv`~" O#8$m6-/ i%GG$|+6PA#)q]Φ v'^ G-W3GRZvu{vE|2ޖEA:r`֭:ІD#nHE˻0EqXd•L*yWNi h:\ l$شcdV˜Ch](d܆uVbw m"Gsz!0L_MwAR +U/~)\EqWuT|,n-*'бȈ,8{a6# O1EeR}jKf& $xSbgwrpƒ!OE(Ue>% cPN#By<$r {겧Tv:W:-J+|R ƆQ.Hf5U&A㎀b@TƳ]4i\9, n4R 'EkZQg̳黎X)F/`㯶hOĊQkV\xXҲ5D6yTϬҗltB& R\\!nc2T!8 }:ҞK0*-"I :{S8 c`]H>@-U \*Q*P'dH=ߴQ;l@o?zW_gdMM ƽR$Ht<uPȃ>m?h?lEo'MdWŗ7cssӧ17{sgsw+~ts{xsӝ7p+h@W}r*-6-3xr1>NY{\(Ћ K,} ]ɼUN@']495(^A;ق?zHC6yR& wSH$ UN_o|{_33Л(JN n-Qqsc0Mӥd\b cL %udl1)J" <+FїES#ʻd%%거 )e"`!x+돫CZzCW*QS&6eMTw*+cF?6$:: .k%G^!dd@0fx-RD@A !Y}}6Ҝ O''gduay?@1ܺO{Ą[LF߳<|z.c汣Dd-CׅCc# Ysͽ#3xt䧆gw.y*|kk#~}Mnk.c,y[oQtR? $*Gł es˪K/0 r[G&nȿZʨ~B߂2PW %򮄰L*cqsn qKqbY9mn= xs-> "#mxNIT"RaF$ u$IYIINC!-hFN P8K%+(dv<8^U @_e''ѫHUCAL "%i*ܗAB%'%ϟg?)fy^l?y_;7r>܇5-5'ik Vu=6%aa=_'lVXO6l6_nzjIYE/5'ڎ_bX%@-B}ߋȭ%zC֊-rkAz?؂~l7x|WCKұk{54 E-rvuuxMt/B6JUiJځ&.9H?/KZ!Zz%>wG|Bf!Ru3Փ9b^5|o\40b,Z@:DEp-eC <)Jߎ ĔA$q4Ѩ/9z0W2p6Otƞt{o|$.R˜eGĐ.-ODyڻAãGuiq&?Ft@+ &0_A_ˋotF}5 79R'uƓRtF-+}QݙzM)攝V*4 u#O .b7 cJo'PsxqOB>EOWSwS*? ?Ó(uY拉~%xWNhmoDlG7dDL@uwg=Pk]A ( kwXM8椂&}KVфoH+?V[~z_#+v;_z[. WE w&(4/!*a {lYQ"uo1<~rgXxObKU ឧn/BQJ?IVˊD[G#CD@'@ Pa(EK}Ue qԉ %!O?0V*^.9,{_17>%X[ QޕxWn6"Ub(iDU嘆d!LRCQ#*8tw5Y=R eG zU!d0yoDd*iVš"X~p97s? F.v.= 1CW2@㌤ *΁R# 7Rɽf ] Hs*cLCW/ԓU:$9?X^NOPE!sak4ڪ+`݉&OBL'v@l3gߐ(MRo@F(Ly )aL$CL5,>pXP+6t؉I6j(!=3* OBֶ'%al)e~#<u*]]_6Gyd-i$)d~~P ~\8zpf%UX%; }g$#>'SRUxŕ`'N X!{BG0Q=PTu7Q٭H<~DŊrԻ֋]܈C.qf ҋ]а_eKAjrʈ]D"bc3U%A*N09aa.T:XN4%Xb| @t<%vZ?eOBa[7@4٠ `IZby [ JN+Ǐ@$.Ɍ,$e0^smǑ6YU1 DWC9Q6cK=jH:y_' %/t0B Uu.sEuB(`bVGą;YoYTA Bsz- e3uDc!,2vUsdXD-jn]W_VR{(30RdW|1n{6fLPC΄|1.1 cULF \xF:)!3{ E<xy%F)mTXCAM㩨i*KKg./ׇ `kMzԤ3`uXT&'TfLQ@"8KԖ,,}?1-E~|kvԟU%frΈZi_ m-W753F_S-ęe)kѶJ+tCS֥j5^-ieSQ+i2'# tM."V%t N(b^줫3e[ XrfQt2+Lad;5Cxxh7B!1;x;\6}Us2]^JmcHj%%BDX(Yt' "&1}KgjcVzgN#WqYEFL$2cbFXXOO >5I#޼wNr]H6ɘQ= ^t.hlՉ3)%U*$$I$l `F卽H w3qe*chFıY:% $]g@i˹| v21+ ]NI-P æcBV'2Z>&Hj>T7ڬJzz)〩S!cQ\ FTE 8,#8{JS{8u9Xdg ";\2t<@fn+12N2g "1--'K*we*$ڷg"I~l(f˙j!z?3=[#-R#v.߅|wZm ;$cVFoҫ*#6~xm"Wfٓ.>Rf"7,hv00 ?|۴)Ⱦ$,Ol"V c:M#FxƾK0[j{ o^}^( ^) q4}[yÛ\svR:*,Wep'} 1gXebnhqå_1z7FCbLJK1)yxфұFio;5:5϶5mxuKM4(?I $[kqmB*Ynl \$,׃}>%i+P_g/t}sE{be"+Q",}-އCjc"7(:bwMk.Ů?E>Њm;ϙ=$2Ē, 9Vh&<wyTӛSՂ nΥS}Ģ$]?0$ ' qg>6 tN:t^bHtZ膠ҝ$5/L0f:&ksIvm)$ٮ8OAʪEq}M+p!<[f,R`.1e"@¨D!aYb4:p?{jD`WRO Q-1Dy[f% -erl7)-?;k]L<W!`6??gu'P [Mg??~O&$>LInlf[?xwwwۋoy@mF l>A esu>LeC>d]탕>oΚ|q>yO] I{[ Znj u?P{B@{?]=Vt[FzWnxWatZcl!T;Z;eS[ߩj%j!,? jP+W  숴Sf FS|ЩҞ8T7ϚX)==<CBa\YrL`~*)Nn;/'%%0huڸ}O=hwH"wiPNWJTwS6wSf[k÷yӪFuh ~ zb0(> :!H _vja^TKkc`{if`{ji4Mhö B=s t 5!<޵vZCfнt?s~0ImQn-gIq g DiQHioS`X @ab{x8C8 t!Z[5{%ZIY>.i{4ɘUMi΋?? ?0ýpxqRbO77`%%9Mo{;gϻ??7?l@P@_+n9W ,7w?17?olO~{']w̮ڽDzv3Gt3GsGuGvGrGpGuGC7Y}2n1OzULYOdxVg!Z6:hvU(*NBjRzb̀9 ӿ^Xtkv Rv)\s@\aa@UZIk+cl 4ym|0+"/s(GjvS@~ְtiN U|esB̓KϹ8`,807W<0&,',+^ϝgZ>~G0h93q@>{;VF.Ơ,~pt{.>S+FxLMdKFa>" y8k֋}n稬tV<">H 6b^1f3,T.H)T Ti^o0Sx\ R]m9ygץG 55EG^O(_1EXxܫka`̮ʵ>YğƼqPVVIu4 K{+.?8VXRJL ̼)V Y's[?!8V.;qqe55;̼b U9Q\c4$Y (R5CM*:-pu+_hy|5m޹z҆:@ ;4]Y J_DGfrΰz)㟹 > iܢ',@:wZ'2<)?|ZEq~@0oB}qd"XX'-,DʄUo|(4aʕj(PO٣*> (yRd[śi21-"QNs` rv3?IE 2~`9$p&PM'6J#tΆ}Bi 5 [\ &w3VG*GtQ\7o'rΛbaFg$ Ptߡ#WR'ÿ1o촡;? §Oo'џ:iaiЛfNHÃU-ԶOn9[ ]%r5J?c< x}%m산aAB=%RAn7),m\N!]Hط5mom/ oԂ+$}Q!҇꒸xKuڪּ#'7289$GpWd; ;`ʹm?=~+Px#NtBξDN7Ov ]K g,LP-IT]H6SoLx%xRv9둆9&Eu ߟidk67ܟP/vjZ9N2Yž\SBMfyp6ju>.\@wn[??䧑s k.y7,!3hwT=deзf2Wo|(~4=2VN<\_P9E=T_@9E}CJ?϶v?[O9q3{^k{Ik:_m*ӕ/(X2׮_?dM)K .|iJ7ݳ#칸ZA1M442X͛/Wz1cL)P N7(PӍNm9@T1,rRy22L+3CfiIy@;VF IȔFiE)L̖^-n'Pܭ,QJ@Z?Lr4K#!wKZJmۙA/ m٠ʯbA$clzcwvc-TSnh C٫Eh8 ^J2ĕIJ_Gk,MٴOZ"%;MjS8;YqW⸶x #k&=kB{Xٵނ|błݬ\{g;hwQ+ 뾦V*LQ涰 anԑ<<'V\0|oY0NpΑ Ҹ օ)*Mj=S]O )òVѷ+U/oD8ܹKr鎔'x9ڊӵ'F6xY9|FR$웱~Ęu>^'rڸ\>lw" ap1ǧ<5 [O*O@L qV(agPcw!~mcx qvYm_5vS;fV*A-~.3Hg_A)/kpD@\P:K67`C;(ǜs=Mae`ObCd1)ˍ/\O cIΆO䖳['•PMkW? (%2c4eЋeI+_3Uo wM(Y3&gJ!O=zكIz[E|0H䅝OPһul!aYz=Aה}HuaS۷c&^‘6L ԙ+^`!Q^sN4Rj\}xeyP ^l_IsSKlY茺6uTF*UG՜fޱ&}h1q+j(awl9 wF:.Hӊv]f>'!X;&RL`Ǩ`aO.hՉmUz@?Uq)VLUC'_ Iq.S#jۢ{^KH! fol$9w=1[į&(p8Kf  KƎVj`xhwd$οq["3˸V_;r>if͆i_rFقJV-cq YdzID)I䘅B,K66"2LK+m<âMҔYգ:xa 2 z3?zΨlZojQ1 C,HK AEOz(K_ymzt6hx}O}pur\We>N *`_09c=ָuOQ_[͐"Ɩt1)7iZ@CNuO#X/K6m oJh#(%ZE]Uq_{lVl,Z,_zoR| I SA6d-˸ 4kq EXzIubB<2a}>!)>9(}" %>] )tHhA)cxuCfsdT> ,ĵW8le:, r᧘RemT+G9cޞ bJM|3} z'm8gz:SB7*G~ <?;gA%/~/js(>\zpmMUQLmwX}ƒ0gTBfju4mҭ[_\ z xqZa?Jqz 2ʖ'k5zbnx/vsFQfF v6^2swuCAQ0b͛~-WEYM216S}o. ӍGS'j|>=QNʼnفotSd} ]W=[Il]j ' Viߩ~M6ʲ ]4_.a n=O%^_{¹& i?mlx[3G) 8} BaG mvhEqK0IEcA^X—ۓi C oo 2pĩ6{#D 41ֆhGgckX1yOC#hh{#89:\x?{'i :w?ZS,qb .WlprL?CUZOa"Og'\tHTn =>CHb\ I>@{{=GGX~a) 7j*:$-VIiœ+0X^k 4,+K#V8>@W7C3N1-rv.GWzQJI{ C)8y4ȇ檳ïӜPĶaN\JΣ IѦ.I+/#;!ޯ`zy%w?/bks* zaTḞH$SH%9b,av5lvGo93CSg)2 V(Z @1r<%ޮ!Ja&zmjŕN1tq}T~v8DTkz9 >oJrO}&U8C`g3AozAEZPFkJA4C05O#Jp&Ǡ4:.QIf<8qGd(:r}R[rE[vq!F0Nz~Y ,akM5 5Sk J g$ߐfɈ R9Pl5־6gQII<`~eף9"d9z].Zbl@\d+*+1xgjg#y # ^J1{B;FŢ/dM"%}`n~6JZr]e9mP =f)=G:|e_N=Ҹ0_ZCuk`ᡘ.vFdOZ+Oj6sR`/6܁ʮ|# ԼLk@E> Rn{п(K ,m\+b܇)g8=-BWD5 ӪqPOvҜfb.EvYc0lq>CX,=/L3.|ZE#CђγbV'V^V)IPe2Ф1u/d4g0X<(o-LtXȨscV鎹'R#w ڲE\a3ILy$ծ.5R=,u)$_%7}4b. @Euz8z|Wa9&CdV g7:υ|-.%. :?ֺCȶԾ)#Sp ysWn[b)=f `.94ʧ\j8Mݮ6R0Q+V $]7T7YIq̪ Mp;. *-әT B&&> >.AqYdXK9=.7MNIbfmtv7!,難ӁTM^׼ع8V'atB쟗V<~c^~@wnRq3BM1ʅea}{Tn+7-?9XgYXe[EF\HDFj}3 )7RbEZT\96O?e:mf{[0Cnp`K濧v㗜iɢkzh$#2t1hv)rS&Tt@w\zǮI1C5Bj/WC/6|Q@GI|N ,{tgs'6 OЍ[[lnuy59kxw?n>C~ ?Oߧ,&Q4_34ޙ"QP?XO~44u 1jؐ7$]dH>_tyMvۍf>ap8u%&ec㣦e2lxlWI@kohxm خ6R΢i_0Bwr֞:Կ)G%frqd1_)a8HP5 ǁԈQ\|́UAly 4u5Ap#TBO͟DϚSc盍GϿ6{Þ<}Ⱦ_?up{:ѻZ̦_ v~jGٟ=}ְ=C~?p%ӭM${%`c{ɋi^ݧ %9CSЇAļ1IW @:XoO~LEFE~9tJFn` ⨖"҇9y MEJl6ObfuiWQjdJo=<(apNf~Oǖl+d%QmxUP%<``70'pfDrIEr;;I~onomm|[nԏf/#H70m=YH"LR#нDhXU8S* 2I+ gUmT1D#1{@m;0[)E[T_bG\=rȉ l2s1b$I'k"ǰRZY*K1%|ש):Q.aoazT|:z RιX̤h3mx6NH lf Klzk.#]hfK _uX f PT7f1\~*x7\^b$|ЖO],)M뉂!q$qSϊ 3e#·tf" {Fʊn7O'Xstcۆi5HY̌;ZZڪJQPaf+{MsduBK9M^]u_a ")*_fœ1|a^gLGḀDnbA1طo)6 2)"N$S9Rb)fj-M֏='Px5rZ!R[}{WǦʢRkV ?'lm&gH. N>*yK9SC4.b*Kۘ/**J$@BR }pff6oD?>f[l&܎јR({B]L ړM}r!cA(&5 ܸ9Ύ '3ZuPE#IоtP'+coݜ]p'0W{%Uֶ%/1h*&/cX(0tQ6=d+]RJȟQ׋'A>(㙴:dRY9t|o$6 *" t!ɔYji8 7ChzJ_.XT$#_c^I}KF.M٢e[5Q-mdT1YJf`%h<`1W^P"sXM`cʏK} SɼATP-=ڄx4o/j=r D: kI^V.)wLE!i=i]֝BH3`4SH#ߣ W,|-B%5kWlQ5I'u3ה3M O2<ֽڽC3]1ݘ/;Fd]m^K?)dڼمuh,Aٝe0OSl 0}$fp>& 䝮*^~9]zBR%i7DڋڎL]& JwV䋈@q1rŨyTymJHi5jV5:#ԻM 2~=:!Fz?seuF}#܄*JKU,ee(1֟5Nt k<*[uGmL2{gt)7Rke;j͈QH.)W4cYq=|S¼>/&Xz^zݞlm.gƼ_$3m/h"W 6 J%Hf~K /ߣiO1{yu*ຓ毈G*<5k]㳣UGt]P͉ N ƣ\#-v$$ju=#zR=RbF[GP!oǘG>%}v!/Ǫ2\@u(0xd w8?'hJβ>²:"/E_lad_r71]lW(JU6Dp!;:8<| %o?~KY#n1x(^gZƆ+KRa:e"w{dI*Ŗuz+.t`1"u'oX9;_E#)M',;|R-k9 7[Z&&[tʫ<2ĚJhb&OIE1S̝HDۑIa/<*m(^8LRi@lxF\Jу^R[gTjj B!pʾampfO4M' > y00WbIӆixGNfJ\9FIu|ѱSۗS`^n6]}:=Jqzc%, IoֻL_yhh\dxG_h"7.>y@xC*gq-i`Y 1{l |*,$b&e)%lCvFl\]vϊtJB\\/VZ35sifwgB4S?D4a _$_t{d)-\=w7?~/.pW,v/)MU]Ҳ*˂Anj7zB\CLOc Q YX.sp:%0K=wx5܇ -ЅS PedSTb4,毝 '&<ݠ:Q2)<]'\rMΈįbX+˧HBs-66Bk8Z$ gC8(<MeMۡ F ]@IU Lbサboػbc 忧 ߾x7~̙yf@FbE'r<Ãb z t!%iڒHKd"bO7,Dž|ZbKdb.ܾzBuVIaW_f́WXi~X{CO>%R\.JY <  B2 b1"Ez6jɜTe9 *&E:{F@2Ƌ }QP /3GdPx)yp6Ke@d( B;BɑZGr8Sh0^?>5/|\7L)P捐ZȈ$ɉ_1G#@.='v iBE乱l2P)sd/0|ǂ*h3o\Nwۙu>gwK{v֌qc 呉po>T(3##|"? ȱŴ}M`.tOا,F)RzVH&\k`5 SVJ(Uz )6g`=^ Leq88('a CKx֨^p΃s A)bMc%`Q€'PGaEFW$03' knAr$ZPµtYÛ)%JE|?D&r 85!,K+U;x~'A>? S&I$ Πhn uia7pUڌs1__1Zq/nt2X hf0o])B" L€밊@v0.!DzD]j*#DgTuȋqN|YX;x`9[ _E +U@ )SX b0|8*t⢤F>AIxgb(+j dè$CόOzXbd DbLT# HJ`ӵ0 gE+N8"%0%,4G1GM>1å H.Ȋep"v5,:C ma.Va2u$P Eէ5P%cd{Nj% V"an_ڹ%W6 : ; V>haIQed!Vh߃:2 _\gIɁ 2drMWM+QY8:=[+1uApԁL 1nMhc&:@7VAb1LY7FI1<%ʁf-AJ& TP APZ#&iE)Yojh&Oki*X `JFlz8g',q+pF1L\WҎ7>R ՘>_qC MK! SIˈ}-!<5W̏Q)CXKY/"p`ŊZ Y ЩIsVi hX &siЀB*y(p+ˡՈwz+>]S%) /O"L zPPL o|n zᯓ^|:ɀZ:Y! HqH SڒXX2L8Z~4=A6Z|j/!b3V2]0Of!.CТ VQL*A3$@ ݛ Ya-JA *%,E)L[Sh|P_wBn ԪlBlSYk$ ĈiF#!v&BJWɚ"& YyZVbZ)-2^X: >'J$.۳D!2vloT L ,zBwL"H .Rfaiuc t!qDH<L RNzBST5+$1A8.'vS@Oo$Af>Ndq   .,jbN|2!µ#Q3J˃ 2b;Ve҆.5YDQ< 4ipn?mt]Ib+iRLn1TAH*wհg)RYR$R .$ʊVhghgțx^IG)nݥaY@'%rlk'f3)"Ý3TJ ^xx%M8;%<ɓNAXfs21]i3LS|,T1(NG@w%:8G0j]K[U RDuQؙaNbKt0L-%+eY|,f4?F`n">2tN$f9 1er+=Z|Df贈iŎE~6P YnFԏaR8P먦>eԬ4)w/E.:1pBpt\1ȃfEh݈8Ea&'E,<^W nW0(V$AV8\ ~{HbFyP8a k gT?'Xp2nAFf9gcFQ?&zBn9Łd|ZAW Xj;z B~J`K@ 5󓙺` *4RTx7rz#N%a9&©=PuB?[7TDUĜ EFEwtHN%D!v~(#@) ~Ab!H))$/%*ދaтqd$:ʭ]g_D_*_/GD bap{NTH/ FJ%aA0?#R- GBw| /2Z"DDwpEA+/3$,@(K`F⸈H.$@@5LJUXL(  @Q9GSS EÞ$wP*Pq$}a~$!H:$PF?&/%RЃT&TGJ:~GgDu.G_?'P 8 :MN ābhI'jtT1Q1b>hA!!0?U_V8C8O)NR"#A.ah&1a c DM6Йԫ|2pj B ~gj B:#,hzPҮ[Rfr } EU>P qk7 *B/PSSz|pjuH=@\h` FU6^p:1e(8ԵJ͏QL$@ UjIР $2^O~H2Jd 3 Q:; HQ1x@ JIW*Z Q'#>Z 2LJ |H& Yag@(>((1 e:d&=ոx?E4Z>S ]pB\L HǞz<{Ɉ}vGp#y!r C8loPyrS!2RJ7RaI 8s&>lik1R8b}1æ[ȷ k)x D2;$!v=򡃠luy`o&2͓8@1>f 9 5Vv5iJp!x g#UăNNe B.Edh ↀh 0m`W[T.vJG9smcƙjwc& ˧E aakvmN'rgX,o7'_ LpOE3LȖ )6 P -iت^[P `(ϘPq3ynɉ:Fl+ i~'яM8Yp0K)HC t:5dXRR݅[gBrЀA@<ùʦ:{Kڢ@XBmHݡ3#ec`S TfX*[ |C]J̦ B^ @&( #!PJlD--X*+Ug:"UeI25s^ ؀P+:"]*e[ڝr\vDMȉwNL/\(R X2Ϗ鋊IbI=aA4BZJ`yjqHUI/(% ZiN,AI HG,~$.guJL]b'* LOU xL1^-e$-Gb1Iw2 0}QX +ƚEhJç< @$VHF§i8Yܘe$&LYR8>:F'9 PxX,Q$N^'t%[aK YzbosfHC$"*>8dži"Kf a"!T[ i@\:ԋCA]T$:`?#8-& @F z]L$:JGD35TPuع ng ) s@OTž]d0d@g6A! 1gE2"AgZl" ìug= ɚ 9(`NR)tPBPGd5¢")' 7:&<|+TJbRIIU߬DV[i3`n L=d_2"㿻5s׏/| ; ,ŴWk | #H,hu$$A pe! U$1΀dh9;8 C P>p̀OX.,,(hbZ)S(\oQt {P!bifG"): D^,YC,sK^Oe{4iR$7]S˕||#4I!s&6̛aKXK]4#/2c&CXx$,0*r-%p]|Q샟fg '&< s%~P_4!P!ᄵ CZ/VbRvBs>p)O?@`4==w'> >~$FCLo7T |{yRV5++K$ňTT259'BЏ $MS EE>Q:x6\ԕEâ8r=A-halRi#Glvl7/)ȥ17l֠[@ .V "1`(6edN'ڸ5b(F+ 5_)R2 ba*P1W,l6c` cs!qFUU!l=g/D>˱w vyvRXw`bLD TMh(OBN9 dY@_,;HNА,C{osrgՓ*4?٣.U>%Oց`{F֗FEKTo*Aa'!̰@gUC+8.N8 J@|+S:5T=rū͜3j8t > B{H0=5' 44\@"!8f2.Bh`6 եayTd7;VN/FW9ai^)I?$;^͂"r"gltAC ^U'=MLQl$g[I!7zRq b$VBy%HmU*D"49 P2UjrǨث gv9giA)}2ý)Wd`\K'4'^+`3;k4 v\"0 K8Ag,Y{$ݩ*zGJaFݟebpdY野&{)]P/qMT [%U^Z8~;SnT~ efW,QV%lFPeX<23S kn h#dhĄERyDJ)XN1 łnE4b` `7?% ^1 +,4l-F8`9@ k;]"#Yg: J̀1[cUm+HRu:qa"'ex&@}aC.{/a=n6Y?eyuBx4*4fbGВ6s@CC$l(FQ\I k2:#%`S3eZgH"X ޺0,V|!/UZQS:#t*r-! 'رU1٬/ΈŐY.V4@@Gljq$}!cZt&)BT/ EH#tƐ2SйNYBAc(-q8wiv HL{&RN>w8 .=_ "jbq*q+Ȃ>H^ͥB$=(Zl/P-ܝ *>u:ޣ@H,>|3<U0; XM{I`yX lHX&r+ŀi wX;_VK+6` 2<ޕ#O$%C1}$(\~B}f8f@][1S F ] ҧC)Pnq!.x :(4I :%u6[2;B >MƱ d9 W!0pl MB3Yn>vءW} >М5O&6&j]V5Ғ[5Ӑ#Iz CXx_@-ŠWPfL9"VJeb] hOln>leD R++=l_QRb|*3jE-I5L_/fuh&I^\tF/GUja^^8@/@d8X,3=6JŻ5ސy@GiZUrz:b]Œ#6U4NY3 :_Y BnĊLN)ug‚d8ir ƫU8:?a9U@AM8)#]e,:?gq8xFg@eT,*@m̲!^ E9z)@,iSb*.LskqEI$C$r" `ЈCD ZEY,1V+p94E ׎f?3۔ٞa*-xШFƩqT Bˀ5$')}$]/ DK ^CP0:wzS0 >vYn=w]:d_ Y zOI2Eq09{LalL(OlvqeHH%$n`` @=L$t"M0, QLF0L ^NTN ėEv~Q(ҹz,ljRsZzeZYbR QWaY1 L$!b!@h!ZbHbv8C։į p*r] &Щ;]Xە8 N}FMYRre oa\5G6!QgEd+Z IsAK!ri".*:&3K=т@U .&&K 0,RSBZ-riObL_!ODq@R<["Qj D=9ʐ!SI0phT zXǐ}h'\3%ܨzq.N@k\̹MMct\EWI`  70fALi*P)R@|@ a$N*Dfb8-L&#wU' ܀G+xq^M?ff-4s\OH@c>(T"DAiKk8dJ-abĵ6luXhf:`N0؟4 -JKBX-1OHQGZPtFRĚX& <&dYLMXqERuD{Y:іsc`C ˍ14嘘Zk6F.hK/"J"kI܄0= j|/[EImHS2EF@m 92jf:t@>(]6L8;qS|JKk] ZO\g'#AD>1CX|`sSjE }o)PRd Bc.L9=j~YCxP3҅$r{ , UXtEʬLܿ#, 2 O /ĿbfJ+PgG?sxLdI@//ҏ$N^HW"(S0VƊo X JƊX kX p+~Xw]BB1G 9?5uo%pso_p,8|IXE(C`pmtp $l $eޱ9=QfJ5_rs41_@L*i2ˉ/BrM:{ö  MEamHGZ h1PaDT}G74 3eQ % Pf45T^vx1?eghW}+ "M~E02=*0  í/T%GL#)\RB ;%U#IF5`P#9#FhR#i/NAsr vOA}PAL)P@f@aֱAxHFP2H|:8#i KsUJ)Ҩ,Y %#MU qq@P}k]6 I\۽D L# tpܽ\Q9>OTKMNhrUR\RREXLj$䣵wV{@m@ Sad>EA 6F)զk*n(N8A^4yd=Ne*4qp*>Üp$fk!G̃ITXC]:sPE22Z&56Lejٔ_7O7=G>"‚*keZAI]sœw[qRC+Ӓ0rXxզ|Ј/[Nn5曬[og~߱ξ*,w ?YԒw-RNW\IuIv:rñwWc-WMjZ&}=ycXEoMz t^;Dͨ' icQO>hs^W{웕C'9zO>PCܝ Z6㮝oiB֍9R=_x o[֨Ss׮z:Y]3.~\G3W=v>10!a7%ydw=6o?. >mh6mδ%>p[y[.]r֯h:6_Mߵ9N37X/S*ĝdܧ`Q6=S6~y%=k8^ U=}{hƌ*|:.Ox}G]JG4XŴԵRƺDWiah˭8{峱YՠǚM2[lhLk|޶l[/CWwZ&nrVν;jM{:a}[֙mʽ3/N7%ԇ)_Ox1kY] /nW̭5yWm::/Ç>Q:g, ˯:~4ꊚļhwr"#tm?/dd̩GK Vn[nj~kV.Xb9>ohk\{OK"5=d3}8CHc[/dIfuۭfS1lWM/߫(N:WXԩW96vL{x~rM<{^wlqWhvon4Ͳut8ͦ-ޏ; oAq&_;8w?/fmvaxE/9vu#=m 1^jI'0oaW6Q_j{AK"L}2̧|Plܩ7w|_qӫ);C췦|Q5 ;/grmھbHWϴxozYf?zZ2b{igwNݤOmT3ˉX98sˈՍz}3]ol~货U}=dbxhsE%?^cu>22YV8ix}t5c_;V2䣗M~eT/~+{~Oflx1_\y>~݆gؐn2׷0MbR1g==z)>閯?v5(y>ܗh@rcr~́{?x 7p#~QrcFߜvu=֣fwĮAAn1R]iWt5æYb޶s&x9B]+"}m6{EEv>8\``{9]Хf=ǭFW72rOe+<4cAfs^''b4/웿K-9;Yr.nuZZ}7ݷ>ԱSۗw;vp4_ltWޡ%Ɗ)vGR|+DN{xW_<A=ELs8tdt 5|D}]Cf6%?_~~j59|g(wj^IiH#YT_x˛ I6=2m-o6!8Cw? ߙ6c/=.~Ky[}j?MU~`M1 u c/ 퓄M)/3OF[lj͋A5k\+Lo2lt#_[8^˓s]1\M:yXu6EswQ_,p=\3eg6;?qJ'mİn<7o_lЊl]{&97-/|~>]x/l_DA{n#Ki*nmz}BlJv ?^U%6os_| dX\~_ϫ&̨tvH@ysTeАw!B3mr\jNmV}_zy3]v(hQ:4)S?Z4z5Og;_jkv(^TY|ź)g{h[fm_t癙67<ǂ uMc:8#eUwKMk+| u@}@w6n1/V,&mX֔QzLw"mc%#-Uջ6SFKz۾n7xo oW^ݡQFVhL{koƮ-r)5%]/gw+w{E=`b`:[7Lyœc}ZھR`sOG]Â!ZÅS]xY~n01SjַgB(*z' ;m 0YL0Scʼn7O&.w|w=$4C s}>wFtil;=>NlYXtڗ˛Mc^!?Na֪+x&w)O26_LCU<\'N|x[ j3_>Ѽ{|Mκ>]::ͪ Qέ~ 1j}WO٪bk=w}߾x.u_qe<&+;;KwwqJ]>F,j>vo _z~jc=WntUkeyAM/8O|҃\[,{˯la5;]ًaq}N۷,{1#66Ԓn,Ejc&tӂףDMi5ʴJC'ou6wәruU ^h ڤ,UMug^jcǧ{\hugI9Nwv:? zmFP8Oyw삻W'ww}SNjK?4L)v4nj rC]'t|:xŔվQϹQ=m5Fݲ樎U3. .m}O›\Ý[/.1FQy Baҫ;f"k~MW.v{Ljɷ737[ӱ I۴ͨ{M.6̳6?:P>fݾ[V±fOjʗw޸[eӷ}~D&s+ٽ~ '-Z7\{} c/sdoOL,wo]:sGcnɅuVOm5k ޻՜W ~njZS[%a.C1YjSe[s9瞭>zjf .Ǥ~|z1EsЎƍ/XfՍkV zcKmyF>)ˍt9K>" vgx*|[9{7 {CV']7&pvn U<{{g!*>izM9묫l oC׭70o{OS>6hae 7i|/k~{\=1s}&O‚ҵc __3i&<-j=3kU;GŴ3kd^(_f&RSGȻDFhf6l;#|F \gonjgsuGÊW{nWm]j6Fr[({fԩ9srf .T^6?UB9c۝\3̒C+Ʒ$}w>>/JsxKo-;j">N-47$lz(xHiԑByv0,\q?7*_ҹH<ҳЂFꅺS̏S;[fǰ6ޔMYVǹm !{7:mTܪsg>~,?r G8OWζci,|yT΢ jἑ OF }rxB^g-ep,oLlȾ[QQΏx^6zyԟӷCׇ ρm|=$qtZ{YU fy?E3yFSF=VMIh5uZwrm02_oQ軏׃_( ieMn 3v7Lվ ε8h<Z{Fgz\wwɆ7j'\#lW-{)Lze9>ZoNq_*x-fcɓk$;c_kF48Y`w끢ko4ݸp *8i;jFz٢ܛ}-r.5Jaa [SBkx't8gaptڒ%ude,??L.N]:4H^_ļr|bwyQ:tiK'M;^vj'gj&y~+g;"FUtjYU_Xԃs5Z1AJъk]3yƇE{-RmTcUN*1\7|Wh=Nm=5sWOrd}-j\?SmgҢqYڋfM/u8"KL҆i34+2Ԏ>?Q5핝}O=*zAqZ48x?Ϸ::GrBG8gC̹mىW*OKI75C6~ˬhdSUo's`m~z[_EcU黌<<[/jm#q́ښ&(/ܟe}u6V99熯CG jN<~OAyɮzcyixb}yvX~fࢅ)ϓ~⭺%vj/ >//g͖޲0}K7ȅ3;=hUүMm݀3 ?kfYza`W;-kl\Vl +oWoݡVKˁ-?^1eLMr׾R$I69TsKhlkKZ^K瑽,K~ Q*-gXr+Y= }Saw }?E4cjɩƹ\Yaj3mv+=KH͍ډ>43S^!Ǹ&N굷;2yDtۡmWkZū|םy.Q2>ۮal.9Y&Mramszu89ioĵy.@cDsk4[cmXZƚKʏo$UvҏvTUXuo+]YGmi_ͻ/{m|s?mY3:lYդ;VO]ХYSZ;C{-:jƗKG_M:bՅ:m܆/moY)~K_Y1Su:^lX$z;O^~볻G㽧\4eռyi<'M~q-[z\xy}ͪ@󴥖rO>+7툅Wܨֻwߺvʚ,/=k)j3#!rG,uxo~W|=sh?nlf+L ^cIomp'է3 7bar Bvr]:v}htS 4o6jk뺢v0[O6[>u>'Eu0LxV|Q:Qز_Fˤ/E9?7d­N?)h̙=J^8KYryoݷ m83֪u- t|nuo"{}yAV)nQ5n~z{vz맋>m}Usw^]h4b?3?gG_^n6穼gr>mSum߾%; ;Mm^ýW6^pǭ{޲'f@{4nk*!SgDx4uC# *Y`gwLw "JP?+UJF&EȨ_{H{IEJV\tK"zyEiIm{F#ɠ0VM}MbUʤP:=*K& D)RRȓCʇkԍV5G?@RѤmIWq%6tet[^#κoF8{{x{x4w^ ybZ&MO)EUiG3=oS73PhddDߛPf<ui{Cࣩ+ ~VI.fw|oyxPny_+C69_O+Xz_WRSd#RKo?Rkk9t= <WZ1R5 Wj: \)`oT Q Ԅ?A]QcF= U+?};WPƢxP|rz/1 t̐B}er s/haϨ?8>'u|28?Q0z<Ћ`q=3?q"UNQ}ڋd Q8Ʒpȧ"mQyaJv펦 Jp.>FݡwT\]XEDȓ[y>9,r$U" -`e `+'gh`5B=``j 30_f|S\=#<"DSX' T/Cf~ς[ b"/)&QНy8sRzDtJxGR6OzI__+sG[<`ԀOBb@}Ќ>cr⚨+ѿɮ`ty#Z&s{6v?&itIj\koSE ][gcoGYf1ij17ehQ3Up_¡03g3jcLF0&"z:g`&ԥ16CO0TmR]]ԫsYUUSW0LlH0L,H&RW]_iRMOV*u"B7ojCd*<ME=;O9TZ<,->8/a*]z$aa yUJ A7)z EMuR50Tא[ʞ z;\)uzX36s7Ǭ]Sg9ohxy&@WLp:@ז?mlm*Z #x wtb{ Z{KVx?e`ouVvta;bV:2V:nw17ҁUYr{A)_?YS!8W(g, JKH7PtV/,„?s-yΤ%tȳd>tkXoiq_t- c+sβo{ҭS:륳:w QZ\&t(Ȝ'S4Wy =o+n^ԗ}?jSi= ܣ?:{D O{(9kݗW}^i3Iri-H#cBs侺޽} zksٔJ>1տ~3oyyLQh?;| {(1gL]{:<|.uHۈ5k_?zF|02~]وo#*#ăFpW Ndߍ2GSf̱17?gc̰1W '2P|Odr32GNOd=9ND渂Ecw1W是;q%l$U(XKj*xIT4ip70z e$YP%J񐏌z &M`_\\YSAs:JAU|TQ7rޢT6>3)^S{BćF㣁x,meĠe$EBZvHŒXIʖBIy4zBj/"OZ ľPf~Hمa2|oj=S/]2~׽׿o[/{/~>/9ŁR\RMZq'gF;_px3gw$d 1"@Ҍ$0kɰQTѰ~%Q;gn=Y_;So ʱ%a*%I]4 e! VYL1Ww=0AmC75V(Ƹ! iﷻuQB{)Txw~a9F=5s]6@ =JbJ}~vL(do$|&=>$*"8ŬGq~J49ـ72R xy4ި'3 x㻾,(^ިgƳG^ &_Z^[4P-1.%88;g/sQ[m >G070`tMzMik0md)1uhY MԞE &U`jܚɏPU̙[; L^F ȥ)1.%apl쟍Fky՘ &m'Q=U_ƌ< v8ױvKs|}6smE CwD]u-޳ėREހ}p zQ9ބg Cm1~AۡK/ 4Nx,?{< @_L4zEW_L`!W(n>/G17@P)hsp^Ι M@r)x&)֌_$`9/eyx׋%rD'DN[U[NQXQ>""±"*y",R"<~G?12}D?3n($S|ۡ _1;AWg% iҢى7[Ƶp[`+pq*t H寷oX:'+%}HwJdL>3!<ޢ r0%_s6*K'KzDH%':K>/[$W[gS-x%S"!R^m8G Vc=un sGo7cyƌ3>Nxn7>?KtkԌtg;uf'ʌ#3g޺0®gqnHw3>i'+yqs0V~,Mv]!ỶC(Rm>ĿBLf3ُH$Í= n7hRٸ 6LO?*vn<s;ES\jYш28Q 9(-y0e嚌1ͪy/#nmUs`H^zVCKfg0$t?!X ,mbg0$t'?!m Ėag0$t?!?!ɥGX .=Z6ԟ1A(?F?p fϳXYb&.7+ oggpV՟{X~vGf͹T(kw84kKO4`coFhT첨-lFf)yݍ`ۮe&OE7ok{nf w˄0[$Ff4- I*gu8{<&**ǥ:!>Wo ު׾F/F9>@)ulv5 D)8ںL)T~qSn"byD>2k:.Yf+D)~ح՞ %xn6|NXA ԧ qfsI Q )m 8~e !cگI!Vsh6 Bh_U߹wΙ*xit _b 18$v%_ !A FC:|nmn/.nnf$:*I5 ة5+ӂ XO1aW'@k:\34b6W־Ԯ!;oI`dj?ئ`tQ/HAl@\fc V0D.Me2s`DDlL_iNׇ7A$Q,g Z CԪFnϿmaK1XN%4s-PhXΤ,-DUzPN5ממ\ -g1[D!S0͔86@z TdriNXXv OGWɖx †A%'wYQWry <뭹4 \;Bu|/:/T-ɤ$-c mvLc} "Yz6a[VcpsYfzv{h./Q\ yIQ.e {wC\Y˷4IDF/jKZl +E .򦾫zι?ƥߤOe~,h;ߚC#u6{jpicǀzg>])0i>2Ɵ9P[z6 Ie#p/LTiมh1$>(Xݥ>8z}0(qkO/d#X@ &3߽Vκw\z/ŚaUOm7BoGOV)hBQ#)?_ta$8W$A)S{κ}_.Dx$_IlZ1Ռ돰UKbQ-Dⲏ*(}Lˎp!d!' 0A"ދO38OSyAk.G>!|͵SqY5U~E+- ȃ},4.wpgi$#2ZwɞK*oQS[j&wS?wSǁ9b~ ^%Y$aJD;Y]`zZ1瘪$yxڐ^|6OIG7ق}Ns^ ړvȍvN"]XtsLjاM4c-DCWt sGhf<:b>u6e1TV߇ּkhґiPϻJ>xX-`c{e9f[\{)I`з/yg`zER/GhNnG1b+E} ouSSY~H~Ӓ|3_)g֓iڧ0Qcx[3 DDn;M58%i}h/Ɩq6i$C۰U[^$/<[86RQυ _;w-DDIL;}iIҐ P[ԉ76`;F> ZaAF` Yun eGYuCy4d}ْ}/ڱA21$6VIyhQ~EQڇ n::$fӠUjY΍`r-9;hע5+Ѻ6@VY9};՞ۊ͟Km^)kWV4_Y:ae Yx q+к?;Tehnm=rWx+ټJq8x5ޭ& M=#x#_Kj8 x1HrK [9I}+Tgiq3νy`Ȣ=jt) B2=RhXZe)EҲA]Wj]wh/ >0i1IS_fyix:%Y~ F<1MA*G[G&+Qz4;QݐaGGb{=VXX>~)$6Y4N/XoRrBVy 9FCoJձ@{+x24$Z jOm=%*W]3sv<+iTjH\yTm'6 lݹYs۳08o8)&!oXH'\g͍ޜ]1Al]vHkgjlrA}_=M_{sC(2!)Z4Vԛ%4?꽡K)!$ ,KuATP+_BSBᕅ/*>|!za|ӌķՓlN:1_^KE;Ԯ?;yKƁyljXmVwi ߥONPSlZ>/j6Mq5@VU|'k;̷Ĉ"lM{1R֗ `ꋫ4.`3x56ν9=8oS<= O B#k-|!ꆍb\fF~f`>*kwƟUm/la'wP!+a!E-RF(-.@ZO1W\SUŅw/Aq{v~p)KGJK6.}cF ŵxhir೔R\4T3{gZN9ŮIw\+NJڔqC]˩jW%}b"-T**.<竜ZXQ^R/&ґw*pRZ`Ejnv';g^j./\5yy+]Eže#'\[GvvQ嫨pU,'x32VwW,+w-).:Ha8~`x*W\gGS-nRܔ㙓LzfLQf̙d9s@Q).;]^ae?Y*b[$Z\^瑓ee*9s(Ë+4s&P*JVK*Vd6 Y~'v& .*/^65w͞9S9f89=J5#K j{UWEU4$*EW݋++.H,|p*ip-.("5eA9ubZHXu S.^;˩WHT*T.[VPٿ;V z2usrܔ7sZ~^μ<J?*GV~gUWIEz䦲-3Tbj_@'Gvn([OЪ].U]%`#)kbPU VUѤ%E4r\K R<#+Q8@.]\ T򥋫*aE-D ^LEjUPEbFp6bDwTZ=R4:&wWxtpmNJ!ڑTvj,PM1,pe.p&$ф:%թK ۋ*^b|P~u^vTU,ٸs5;Aإu(O!y2ٹ[]o߆lK#Ō;&g_\wQ8Eww[(RTU)!K A0`Sw?~Ϫ)!.l?IMK7Э!:a`AŘ{}<pPBD1mSBv?O ؝Ǭ+!s3M@Y (j#Fc~b':X7\knHqpxZߕtn#;Bt O t EpLt}/,JH^\D"%{@t //貈.mUOT._?* #н<øt*!{^u![%o` vl ? Cw@},S$]vJH]"t;rEZs|&0_aᏵM܊G:,y-X&)jDxַCF)d_+% `'fh]dN#M\aa;q.p~R [1\e(?I  +8㓕X|^>Mcg>]~ew-W@Dyg[Fp]o,ۻ'coB-;tKP!-ofx=_hT7g%~>bbpm4/ď' D|. n/[D1LkKOx>Fp_+'-c|GX⯋l!~b 8"~Iq]@y4̋Y۞;fmmoo7RKwg3 ~IcU ;#Μ_%{,O-3xs\h=M-N9exUl`뵨XH-/,(/V &ѣLJ'mik]b,vt +hw+ew/-.S[Xg'! v$/sG=2rȇ=-YhIŽc4w(x#htsd ·m1o( Y5|n+Y\S#چbY6rj?7fS(aGW>ǘ_HU&gֹs$f)9Hca\4kW勆,95S>0fۣ5̞1 U t媋u Jequ~e73#o5f͈ݬ^Nu;rF0!g73bmHl8tUb2M$D^ O41]ƣh c1achir@ "J*K Vm)Į]U< O3{® ZXMh`4VJs]e8ңe=P6'u'u4`X-( Y9UXLo*Lam\,,M7iĉ.&.4,ǥm1nE LD{g18KFR2n_1e)YPk|t8RDfT)~dh|nlve SS(`w386q"Sx>tFwH"e&,a6mr~sߜe %{2`k"彸E?Eȧ8}G#/^@_ #7m?B>""௏sm7.bw  `_!|pv=0v/F|4wq7[gr~A 2 R x㹂4x"Ӏ7; xk]2F| |ot1Wiy,7{5'i7E#|O~o_Osb xM|ǀi_fF{ x)}f_a1>~OWʍ!Q|>рwesaiU?؀2^j~b7>ksF5|?܀_n0k sр7>+xĀO7 [{ Lr)^: )*88{`FC5 3kܟ0PŸ@0T 0>9t ?(p:ڄ?c҄?ʄ?C vJsx0W9lS9sxpoE+I?_~sef1?\9T|sp?Ep++ݟMRt7RtPtTtRtݟC_ݟC/CݟCwW+?(pZ*?c)?Qt>+O=g`Bm'ԓ靛ɔutJ~/?Q:(uڍ|lޥXsL~A «>el`7[mvgjR<6D-ۘfox[mXL,Uf3C^6KWoQ,/ÞDjਡbWM(^mmп뾶VO|C}mC vܿ~ܿ˃ ¯qNl VֱԂkB>3}mXܦWԋsǽV¼ƧNߕ ڇ̩NJ˴^0Y~>:%pjȸ2vﰱ?ftZw l__A{ʊ; ,G{-wiytӃv3?G[#9,en䱬ײmaCP&bX.ܡ3~sm9+(-D]z+u/`/1 ^C1U0473Kr G֏  ra LUwLv,י|h:8VIqyjP{$0ۼ}vuyj&ťc<8ԩ`hնaY7Nc$M[ۅhwT`\CM`.,b=1][{Z9G4zy]{=-%mN'6kv7Q^3G!cͣh*~ [&[U ^p&?:֥36ۘ=NPڎVC.id9{zN^$nCEx; m[?G牰,-bXyg;e_X>0}JbI~TmX@DzM$@̯V|\2ϙU7б9|UO{?uyٳiv݈= <@yk)aQG]Ž)gOоI>:Qzbhwp 79i&+|'㬔g!({nZhEj[kP<΍SwCi|0KD:37toVP_hbڙHz\G=~Hc8{go҄I8g5Y}] 8 .>(fN$1čg 3^sjۜ`ᬋ,*ޫr#zk/fkn,ZFTo`[{@H9QţNDb^_Qsoo!I-̿å?oNRֲg I$Ig\L}%jl > nm; ڳֱ-cح~okrY1{8wL,ew*޾}qpT6nG; ?B0:l0s  qw*&V;Xӣ5 O[t =|%y 8&2UCghl )hQ_1}\puDOsUl_?ֿ'Q[̽:*P_\l@&8orR4Mxj. LqC˛K&`0a-Oz2{3"BP*;~.}78z Fr kruaj}L'v,[H z|k?Mb0_{?^v;跛~3? ؄x^FR=e=Vz;`)s/#9-7tcFl<\%+G=iքuFMɞMh 18Vx¸zGy"Өy0]}v$2jLkb_*7/%PSFؼ''yX,$A_odoCu?nf^$h&DHLH[!#!;.17`wb'l)ڛQ5}2kem,EvA_KҼɉoxoŸ܌/s !nh%E>"N|ud+7{rNRuCv [3^s"yLwg2yyDy?Cz2ܼͧ6d lݪ~&d$v⫽5gԮɵglgNZ/vz¬fݔOu2& <60 kS({kjwv LMĂ7 B*Ch1SCmAhK/VDm".WoZ<7o[|4XH j\{?U0LJWk4elI_6FZWj Ѐg-Ȋa4= I'Λ绢Iİ-f{ŴSrNx6(x)߇`aK#ƅ=0g пy#IW=K:9O xw70v6U}^"49o;كSGtM(O`~}.u&6{N-%+;_>~Y}I@^5ie[eM)Dr_wh6Uu艇=e[ҏX}ye/@"gzSS(Ÿ_ $*}M ~Bk "[h7߳c*oO[>Q}?4k(/;{ |y2cCIhgyH`6y}.WАtVhӦ%eԡKe2G zN.0xwy _NjUΎX&ߚS]H(q|Wh>ccɶe+B#G*xjǑN;*PB5/ چ٦̋-mih3ᲂc._l,8lsLt-ϚXȫE}ކu)y wnSWiMA`|taE{aٙ=hVywx hHļ@;9~>w iTL73BHE_ }5\pWÿW[\p_E 5?px`ZeKkc 3 LK<y)tQ$uFC;=vhE )t Oau>JHaR'x OPx~mW9mqwAAm"qjB K9jnδ[ƿȔ'!\'\IȜ>6nmlC:ѫW;8 ?3lti 5Qk$O2"{k%oiI`Q>^3I>!_;," ־.(:HƄgv¬.dmXDSߞdOр:_ xi|h-vf$$)Qay>ܰ@M"|)'?cr8_~COof߯P:Y>ƯFMQMKؐUkʆiLEG?Pr_CP&y>_QU`+qMdC!<>$~?OxBNoR|&饼0A/;gnC<޾]]J__Lҟ">DG)^a5IT DDOpa3E9ux].^ڄݷ "ʽz'%水 ɽܻJ "%>78KM"^D0(mcH[Ft>?$g,PLAl#n향+/iz+Kv06}D8DcE8UDX"¥"\-‡E7UKv0(_CD8VSE8O%"\*"|XOp[Eac{E8DcE8UDX"¥"\-‡E7UKv02.@wrVo,e+dǒ,6 l+d'. >p[LVQ%#!mHku2hIoEBLzw PX~Fll %4i%sP |\d,$Hy_mdxvtՒIo>p%Z-DaEWOKz~.0v[__H&ҟt-CV9<"p7Zҟ%BǛv&%䗎_ Ooa@%Sg=].wX aiWL/KK.ܩ^ ;,z9[kOXov6agQ 7EE)fT~%p=yuПF5^5BH|Vcϧ_BKY |jGf]}2cyȌ >?9oy3]^6{֌O=3^2{njOi J=`_&|>n}T3:+JGV|Y~,?R+-x[7+_>% [hmO%)܏_6E6 \Gw~Yzz\JCء=!𚥾P̛}pNPb'd.wd3l_NK} L|Δx\ϗp~&8Sw|.xFhՂ>M)DFL2i /J|eE>_qq][=h]MB_9-=Q¯YZ:?OF"B%׈r"%~wWQGG}Y4Oi՟_:1>2Ms-BFm+7-,@igm>__f?QC?.9#ϊ@Fq\(~Y|C;#࿊?*WĈq'A>I $Aؗ~^LU~E dsu':M >ק1B>L$)@ c#Y.gFϋ_o ~fvg^~:~P`,fP>A$|_!ʵ귓Eq9Ć\{qJ.+WI%"Gļ#l4A/lM _̸_~E'?.?| 8^ (;_# _~CȃB?t\zEo%z+ӈ2;C.A ]H8@?IxPԑF@~T+E\qsjK5V1*LQx ;ť&sἨvumkBV1fVzAuœ$k.65t}j όX{A-|LS^&EQgV'H^WCI.g0W6naelq'̥[q+5:䧕?K!]9l(A!w!O8IlZFyt<[NBIy6Wgg?ua6/Ӥ\$), *OKuV?%8*p->&l*:[&o`0TF cbȺ/c5+ ?j Yv \>]Xm{dA߲8j}ϳ|Ŀ.<-fZzhQxo5os;AEL x*]G8(4'zünd`;`ӢmhѧN{Eܡ1@7?np/̳Z RaWcPh9 S@,˒&Juޓ62j#U~ 6a`8X7 LSD@cEXD2&@)[cBTOI٢*8rhi0bkf=Ѭ7I,dac`rˍaJy27>ʭeȴӰg-n9S!r- 'TD@AOt1C6s~W:[xM߅ܠODM. MD3Tr`4D-dm̠UzlUR5=.Dt Q9^?"m\xlrVʗv4K"p>X U҉;$ (fvnqY£H.Pr#kۃ͚%ނXk0W+(4}l7Z%  E:Rh:^ y:,$n1ĉ8ՇbR,ֽ%D|#f 2 /g 7AC2ʤX̠h-Jc7G2vWdG?rKD+$pw'U3&1)=#NHxb LGy-yRm|J_e/\̳9sKK-X ,ŠO VZb6>l~ݨ:)^u?^lkmI$4"!kQQΎ* ]dH9M8h*7+L{3.:8RTI8qwT~iIxYb"?xv~|}8C'w|DOŇst=gUQËމjoI9i?4= ]KǖD]Fhz`ZQbt(cΣt*}0da/Bmxy;wx/d"X3(O1Z^xǛEO$v4[G>l +7ٹSß[q,3Kk ^k'0$JLƝ$W{qgڛqov ؤ#CPzxNFf8g_GCkf3O;:૰^}ꠊlYxk#2_d1,Õ.zR|6^_fӋ`py~?;mU1v#ZܳS*,6k@kz=i@+Š^A߰iqma+^?F6x߅>/iʸE0*C!mQݣ_8ly~2%;|rwg܀쇟Uo7k|dSRݴT{=-Gy{Z\$ ,ZD#)}؄{5>O^b&sLeP (]Yd;^4 "Ւ{a>anGuŅ\WYJcRn4̊3b>̦Q/YYٗv0YTۺT :~s%LU|:qW" 'O 3΃[V2<"3&Pؙ؝G|x@GA9S4_bb>!oU=I8͊xK3|O~ńPy>)&i+(}tmFWX\HtTjfxrEr4U(  zd,eٷnvaN?]n"@;<9zzbUn- yE#`M.V[r|e4FL A,$aR:D_sM(|7O_txo=t9jPJpȭ) ]EiHqsׂd),o'<Ν17_Gv`,(Z'굦)N3\4L!Øau, n'P]$8JK,nT3&+LŅ`΄HCK?)4Bl#<@Q"6%iUoJCYY2RnDlR;{Tk*#DXV29Akfp kAE,YZ~[X G,4.~AyЈpZm^뷮Azmwlo5˜k%uÚ8:Pp[;GAMq\?׌kɈ;ʻ goEّ |#B&EϚ8%B*i4~"avKk&3xE'TPۘ8'  0_Z,9CG_V Y" OfL<DI3ذnj9ZbFl&h1S2f>x"u䝯 3x-GWXk10ra8#/1=o,o8TX&"hf^c\ٓ `p! Y+'6%EE"Gp֦+FCb |zwcYF*2xK7b:>-ȀOk+ (a5$BuPIH kK:l#Ze^&6͆F1HDfpPh'GkfAǡWK ]Oi|SdGڣDJPYOWҠb%iS{|1&_q1Si}:)rRh#*<6}銚HzmapP7B[Jڣ<GR]G]ZDQxaM @[9\=pR"Ni+y5‘@+X<5 X;E Cׁ:l!a@=\;Q"԰w1;Bmz(*"P_P7l8ehtz^bU` $ctPwqѿ80#ůMȚ6V"g" T[>ORm8N7OвiLufUb(ڭ@ CDt*q!2d-&Z\x1*:6JƤͮRorITFn.2< /SQ0XglTB߲y7xޱD/3hT(иd8 = w_zCj|+aD6+P=g#!Y f(L1 (zMj^t7A[TV[ZqƨǏc73#~2::{2йFM+B,?f%Ԧ|]DN:u4MH-(3Q%Dy#SP#BNku=EՆxip wiRvK~=BN='/s,UilL&H6C+>Ƒ"s80-ј%'y~[E;dɩpgmgܿ0 (\FfZtOJZa3FD7xT{ .Xڞ=5$#s5i̝{hz;JMT,^ݓlf9L|F{)FfH1{3yL.ܥ=?C*.\k"HLev\qZOyn!:;,]Ans4~ IĵӦ/VϐčL. BXq̬cR3@M>b ?4eL$N/_ķp9 V/ erg_RH: zdh.:h "EF_""J2`M>nABܡZ`"hg+2a-4 =|l-nf X;,>]!00 B?ک %,tUrKҝh5޶[`驔8ฐN\Q"zB'z&86G"ilj39t6M\bϪl[/ tQ0 #@ ƪݼ()PC]Pa6rI 썇Lbkl3ߖ(ѝ.V,1ਬqH xyG:m DP[N^tCơeJyM*.xarͣ8O7u4xa%~ U[8ϛ:.K5c{fY=zzXRNd" Re[z֮Y}=;⿼-Xg궶wv?=98eN[?dG]m7 6u~lr_} ?&E&EU o?tӌdή?og0aԚ.|n7ѽ?ɖW^}p낀KrA\ׯ{n) ط@sjZs\y 5hjx:0i|83A!7p2_c^Zl-.п.s(׏LW6mNw'So=-hi#PP0X ԅ!vM?K#fװ*=3ԁG?U!KjJQeO ȒZEڡ T&U "Qb-+g*(&{7 Z J6 *'ڢ5Pu6K IFK_q :F1**=.vS^猏u;tr9mk^c%Jb{)@Wq|Y^g906p !knvUQ wϡAv|0Yl3QX5A%O)ϮQޠSj=N CI) E讻@zD'<42{ș:'a`B%b"ѴtH=ehK;^&5LGr0jHQYvEj@M8*'?vJ_:IFf l8hV1|VISBB0Do9b? ;Ӓp!J%9qd1/&2J[0E&e90d)35԰WLH v`X#Lǹ;p,䓂\ylS5got!%=< !e,Y4넧lrʱOdm3h1 ]j`"^ b3 8 Pj$U5h0bS[Aw uP_Q>tEk9w\"ޢ|Ou=DBW9X~ !HUg~߇e^ZPb(„gt'E^^(&cmVd|X-HgvdyD(_z]mwpD"F{6E #Zl"0T{Xdjpq0˿b`E)LGYegSbf:+W Kk7/#16O% M꿒0!嚫h39&pxHn~c&ZVV&NDu l _5*1|)a1j 6p'FpN%20[K>ĸ600qwڢlr0$ѯ/0fPKfɢe,nI{Lc8G YŠk`5ߖyRLRV .*+d &A6Fq8n8%H鬒6́e]V3!r?6]e|}QF. )o@㽐fJ5S_~ !\<(`2FqDbuL\$TP2\Π>$H%cp,h@yh ;X4?[9!+\7\$wX%rglE. 2TS.PB\EAѶC/-H4hK~GSL C|y;I3yjֶF wMdܔ\b?JM#V2<4hW! 8&\22&lJUv_0`.1t$pS !wwzYw-;%޾Y bq:Ԍ ¨^Z ZՍn+Hrq>R}qUsmdTὬ;n'3ׇl2pT'/x 3W9up_ xZߛMlR>pǰnCu@M8V>,lkٜ8ŞVs"q50(!=غ7[`n"r1mLAi6F7zF,( IcIO=#_a#V]p*5," ӈ Ҡ؋ =*|b|<5n Rcd5qJ < 60ʳh2cNv[h e~2b|#H^k2k_SDXFBvH ] g@FV(2~jAX-jsGHv:l[I^[O0d9e=7ApUvzMg ~@J"ʶQ8"BXܩ;M>5ۆ"}iKݔbU CZ;BC=ή2}+E MXF[2< 1% mS8CXiFf~xƍd1!^1^.('q PSuϷ!V ~X#$f  sl4,;v"r!P$o,ehF(5`3{^F@ǚu]:f: Y񬡳ccPԳ]u | >|!CϢu5{㻀8S"iM|dSvJfG61(@LpP=nc#k=Wvx*Mq-#oǁ6|`3h.-|ԇ;尺?/w>7!+x[ | #s>͇GGm z-hto#|TrB0> lT$;*NvV_OqݞD x9-tOed34~d7Y2x\3ZƨwߎMfxo \F#j[Ns=Φv~`~O}?~E^ڠ6q5sfپ i;z&yQJ*4V2(1{IMQ`ʨ\O!* ƫO$N藾6c!hDO~gt:JQA>h㋬ 6+-Z)Υٌ-5.fɏy%E0N{G;Ú!?]eQeޔ+cQq0]y_6Yc_9jÌ;"a7 FF{|%c|cDY;NiR|QrM]$[s.lfmPL_`+)ufTlN;f\-LɼJ; @>nђ+*ņĝeB1 E!cyY >w{.?+{x1: WS0d̽m̲al1|rRxe{x ~Ȗ-O῰^ 3ԝZ..?>.T$@oɕC3SV QaR\{ Wiɢ4LNݜ`Nu-N{XDHZe%*QY;0mODz$YyHH9%cSxR2՜7&"[$ba,բ7S_D[ P\BŖZEǸ,H/΍7ĈX rM!9BEijz.UVBN@f2IE8$BbUslatwBfIqU@;{v86֞I:0*Tˢzw垟 [:J>LEO/{\ǏķآtQ⣴.֫D"oMIҨ5/B7]3>j, {_ߦ؞o`zfv(`Fu"WGQ=Re < :]&i*d5aχ`T/oM;ʛ~~f~5+f\ z,ݴahV*FiTrF *ijelA&/R%™8uY".}댻c¨,WjG&^:T8"5c ڔ줶<#"8\a l.-tp@- 譸9Cqrkcl#v00im %, :6#=AKZU@[yU`}Bs)'"큀Y7L ~:Z̢؄wd/6ɒ I3N*CQBZP8Ot"2l\+ћ\l} x D*X6ż}5aI)c,sSGg\(tγ% &89ڭ_g'c 5I8 +4`!6jq!X,`&0U)0aB'fZ!Bģ%ut!`9Dč/] Qsր븶|鼡σ'Z ˶V3t+yrLЎ$Hֵ8v츘2S:NkAE*V+KDځ .;˟KIvk2R/j~ "NM&S-TϣyF)80iU(@RWG3ԧfxW\HZ/#^DU΢/Ԃ#ڬ}9H:OPP8:;זtz.k*AkV#+_K ߥ:͹o3!!l>e&nwy;Ӏ84] 4Y3W\iD;zfJ̑j yʦ@L xaxJS pޚ|V G $4Z_ "[|| p}#ޙ;QlID.+s&zQ71m|+ !B|^ouRۘ z0{"m3%EGܐ#xBu)EcWUʟ}˝-!m|݊P|b87Xgz=^lq/x:Rÿ(edI#ƆB.5sBA\A%"S"c?rYP|B6}xyғ /ޜ̶Gt9z1- k0dK].*L=`f3x:V{(\:+*%-GfWLt^ AˮܾQᦵK>-rf1~eU3Ak5=|OC5>g!Q1`9W 9Er'41,YaN܆ ds`IQ o\VnRHAL[9k#{jEm%k%H+l9ܐiw8Xr\|wA93 ;B EC}.fC>+eH_'yt+R" 5~h2M!p,Ф+mGpcYǰ=,wD9~M&H|}ty!n z( Qx$UMA($y3,5R/mi_T໎Ab?GV Z`v}ZY $e<[TX0P:XmX3H)34}A9p-_^Q]b޳fL cZ'gSQ(2zJq2ǡ8+4?yz)W+K5,C5'Wk# 3J*.pK`X]ӂs^ DKIm cg2A $ϪWJw (cD:tّrM IT#IKL$s/┻__:ʾkDP|ÚD4LijEE7mV3XCF$-zżP C7r(g o/Shuܱ=)Ll30'bV4~a2ehv&Do҅/<(ԅ Mu+j)8 %fD#?0ӮEPlNT,;:A2$J Lм\Q 1wNIe̒3<ֽ^]:MkgJAtdĤ*%8@ #5"Yg ^>T[1Ar0R!֦XZ^k9°ĝ׌qq/I稥y{ao!3y!.l*/37'ܢwBage߁=.K6NiJcfm/&'Io'x𽺈QRX񁓩OwA<=va. BӀ /Vhxv}Ν%>[L *Zp/kL)z̗Ǧ<8AD2"W5Ao_ !M G_B w{1w%'QC m)ՋX",rW"K^fdtVG5$]?ςQSPĂL0g,$1ס#6H8.q2Q]'hish8"QCu_jed#O|٣C-5`$ S#9y^n R2 x5h@x j]b!pc_N< UBqe\Kgl,1܆кIhLk.L67- #4|&w8葐9aKAes-j--LXnpA#Zn1ER1/Qf^p#+x֦ _}i! QIi8˵%."/ec]leNQ!y^{Ȅ$4jJ}- ILjy\G7ϐ,h;?]]5hOy6y|] TKP|B :0'VkٗDP[1bH YeK8ppku*%^:]6]!4ďԩbq\:pn,73Dm+[ 4[;N $-iUazzC˗C@ -f<Q > hnZMrD+%=mP(`.,gpN5)ّ:YJ=D8qMxHH.kmZ_)d=D6TO"PG}ࢎ+H?"z3^՚:]NC`@!o#аOCl+M%0.bK=jx,hZ2$ ${!),^tj:lv;r/ >O!Xf&oװ9<8Y ZyKϦM&Kl41̐ߵxc:mԋJFr(d͓zȅQ06ZT f5a}QNmA8cs G+9PAL,49M\A7V,uI3|:'wQPNbs )W}3Hw܆Բt=s k~lqB㘇ͥ-%.ydҴ*'\ v/[iHu/q ])ejp$i!8$˺9!. M1K2jG9F&q"CfNl)ʥ͐nXY⺠K>x2u(Nr"Lty5ZnQ?\OR:!5#!"TG "@dbrZu)į0hE2_""o.B}e 1Jx ;^6P1rhеaUjk͖8yR5?<3U)eKf0w/al4C n-ǂfx̨tű(b$S-[aQZ%r h-ϣ$j'#!K>\P/&!H +-wGrAMt.iwZGqɡB3SLU8\T r9gkF|Zr&..DDE] uSkp/bBhBz,Cax5(_-kX`J6RkVΡ]0OK l4*s(LRـDkִw"ьcK$n&"`T ETuPUeE(|GBɚFA,&Uqm,uf_#ô/\tl)#r4U [bZ/{xcC0}$Uo{ˌqBi4xv%h)=4.in|@c5˿pEgн5NF+9{e.6l'p#KOyu$$!?`9vV\ /ĹTrD3cIf-+\)mGcbW"4z!Ohq6 )Pj!8!r GRT Vt _-/ƼJ˅qR@$Ky'pL(4诉dPRm[6HɎ LP.AcIYиT*8XboE'TdVB-oRqvU-;3ZV "q '1o&Ek#GK! \ AHjV፣. d&_\ڛkb3 7U/v 630B0XNFddD?1gpxsD©:#]CleR*ѐ6Q`Hh!NkBŞ SGhE'&C|:clY1@ Iua5ɟȮ=tE,0`žO:=/ њ ` EȡG[h~p*[{hES\_^WuduPqA] -~8 * mT<_X|P 3f^,ۼ[ mHg+/{UY4\.wg=yǫ; 0̩ xoK2htL]eX$RX(P#o}Ji&,c3#b` G`\+f$3L;=3@j{GWbpv=Q>!B` 9-Q @X8G ,C޿Z5S~' tހaw4‰hޜ4~f3 ?Bo/:/@t^c&> y0vB" bL`SB{ ,o|2lwgA14i@:(ڧXOKg* .ah]EP {- ~]2"dTCup~gk]E#ӃQ^XY5?MAY"4p7>AψM9O |=lt~s")?;U꒖S*N!HN9)MV*MRNj؅}/Izr oGCh" 5SC34R3)-)Y+H7B־ZccTȦwMq8\\?Kt&_M՞%yxx%n'"cKMQ5FHhs1u9=tQ ⯱ކPó4淵;ߙw(qdOD 1TI#oHth|e]dIJ;j12+'ӣk0׈"oqή Ak )e'6}3#ѷ+ ;( OF°,u-(gIS*Bhv0xawmM+ uM~nF:&ܑdY9'y9i)ưxI$2f!r?q e׫]ez\Կy[(U'zȞZ.lJ FV ӻE~XHO^Ҥ4L2yVNeL 8]lZ̗bK$K̕0(nq+oܖ3qTg $UHnlJ˦jhiwF+ȏʩ:)U6Ya>RJEw9vt,bq杽q DʤBId $Xq0]4kpƒ!/YUy2# sP~&h,⹱wwdvS6Z.=gFBD")31D?JvX "1y ʓ,T:H Šux y]KfLTbj?8-ÎK(aX < PFVhlt@&]{!.&QC9HKCp|=`TUj[ AAgpQyrvK#2-lbħG@ 8lyjJkd8\t BQ舁*J_K70G̮q#/39휒yGd]*]?ȥ43|>atj~kbؐ8u+2ygN#/lڴ 1Si--Ek(Ao?Zƪ' 4R0m+'DاF^ Z[.\헰;Nw>A=xZwww~>?kS}>LS݃=s޳SʗSΟ)Skۻۻj_>4^GyҤɧ8yK9r@GuA9KLG-b_4u.|D^*'B ^l|ȁƛ 9$ϕQ1ҐJuR& sSH$f,(5v8V4zsVBBߜ@DPv\Ƙ26KgB1%g dS9 ( xWUP;i b3 _`+rkiIrx)`)eXɝD8+p J)'\0X,5%`"1u-1KY%)5Lyʮ?7빀7u'aU)08Ү/rS)XD DsD4w$$e$ Y[3@j4K@O.ӳSI: LAŽCT 8XY:u+*T_O>ϴq* Ɂ dvD$LrC[((w:4=?wl}Uk|~>:;1f2̘wDߢ\LXd6K~Vʻ~>\_qæ" KX&?Ag*Q{2`}v_{~^RTQӢbxc Yu:G%X;zYKoϬ[dւ1u]+ǰدwl١8-AKǡl *+i9 {p)s$lY磍5ڬS+ 9,}{F5}[ZHt c=U8fƄz{'ZbEK[ O@WLM3Ыn-E h[p 7':5. #@)Hh2G*ZD-lA~_\ٹiwZ I4C&q rfWRJ=eu_T'OVS/?xsrx5퀨Zy zEVF5s쨁oHUeH j5ԠiJ lꑶԠjL$ҍw)E'ٽgO qǛ_1W9?<OQ?e+*A+xhb ?N|:ޟ; иgRD⩯>?}/O\-yQy}mdk_a1V;ZV: 6:#/TF^4*Y" sk XK>@lG{@/#m(`/& /PkE8`#jj!V(*HD8paww4)BU>?cn]gϸjpgRB)t^cֿc&8s͚;g'9 N{bk٠>|}?e[7F }0AG*xY5h >dC_X d u{?riXDK>jka q!NHab'5öw5v"QSN9G(m*ݎ_I[MZ[k#Hwmܭ>*\%FFD]D*5n$'9CE뭞&'HykO h ["ڳO uQm-eT[иhY5I0V$'ܦV"=r2G$XzhxZǺ4ҹqsR8y\~UX±KiBIrihrdbw ʨ9dc8JD1=ausbɁu@lsξSDix~GEmYCOC?/ 4O<]|7R  /V gBM;1FبΘ'!nI 3<֔r:R.wuLc%f~~$t"g82?n+L;'x*!a]hJPz\ч,d :䔓rŔb`'N X}!o\BXycTBMPݱ1N}u#؟8it(t8աu)[1ȩrM:$6"N0n;V+ ťj*$] `QELՁ%2.61Rui78c#c'E@-y#dfg4+pVqêhN ӫ\Vۘ3Er-KQFf}ax٘>gaVrv׵δ GമiLHGe"qa<גrte). G^_p6](uL9K#Z#Sa) Ҟ fȦN'6.E&E "TV{mZY1cySwTOocYshMZ"&>gJrb )D,?RѠ.Sal_9JՋҵ%@E ۝jy랬Sl_xoG θ_lEɵ}Kd<NuZ=D˒눀rSBF HJPsa@F "0OAd ES~QWDNJ5- [Ko Nĩ2]SSaV/.ln4"ѕV~u::&r»(ZvG䰙:wI4hkt~[8h˩$'"֝"i_$8tOqQVRTV7@*oPt-P0>{ ~كQ ) $t>5krIBP29$cdFS4b hei:eG;t 1d`w)1yرIIJI{wpk KǞٶCvkwX&R7 .D[E#?NRKr|ݻB_0MV`j ŚmnX@&RX")%Rϫއ_(@)ȇֱl(j:NQyM]1~l[w76GDW2I:e&%;i6d= C΂{6jv0T͋P /X:]ƣr1+eT^ kFqљh-ԁqKOPʃS' 6!(u'cw#ȚLl]ζYE@<uFU\bϪ6pHAl=qRlt0%E OQ0Л<$=>Pq4.FKCCv9S8zuz~yvFK<Y  'xhĒ#RoFLaxJ1̆R )Cid6C>=Ay YbQڙ+T.6JT*Jbmo"CmM.X mԾ\ 2Q"'bL9;D3(нu;Zhn^,~Q1r'ݨ((r4ѦPܣ4;> ߋutR|bem h% hOXѦֈmi37eYW`gURl7A6nxC5DKM3Gf@{Q&IlaĶJpc[&4&1a@{P(lnD?ea;M”d&N<6]HVƦ<RZIoy0P=|eW{,9sYE#ٵ1&3'od&7 &$ yMM, xi`Hfw?;k>Q6 SXiƹ[ofC]FTiRnZrs\z~{"lz&ֱi+{w6U׈^Bz-v3-t3lllllll´O̾O]o_Cm:ՆsvhGoO(꭪wa!\H;mP`uXu U wI =IZ,D:Z븅81t.\Sx)[C!BT)n^`q18DM;l˪)?J5 8Z]TR3L`z]ze&JQ.1c$W^PI{) Ej165<IlG.|,} mڼD0E.j48✾\j@2J?^)F䈗.^ho'Cizk *oXY e 9lkׄ ' L $aHO]Y.\jrpæaO W3+nf?78 =f̞&͞83DJH'.,YFh( S|3p*vⓄ,Pb짤d:IC !"F2+hzUXHۑ@P.f!C0pKc1ѥϐy&w&d6_TOVY;.)Lq&KF6hu|fNJ Q(ŕι4H9g435I &_q9.9eTMEz.s$8T\('9Fi>.Ȧ]u?g.[;1eX\:jTN\y͛,dT\WB@(/eul,:g#Còsr'ɝ7:S;:N|sL1fQn833}5xE2sR3G嘅9Ekx Vx`U'5+aq["R*>9,/W" ahfGRNKMc"Ϡ~.℅z;pD AH}޷FzNOK7A/f) -\PB(.Fch'oL)GGtN~6~Q)Y&HG M[4S_eIiQTXbA;:1[NvRelq$M(`TakܯϽ1+A"j@=!^?P0j`3%SKFO #~c?v*s8}5W>\r2%=1-n S-dqJ湀%(__gE%)` cnI kbA-gQKLaψcZ2dNh)̟?%0FKa-3Zg A?ay4~Oa?#)0"9ݝ2zJKfYYR].~=67t]ҋ @-\0[A^=9A"V W)Vw6**(bHRf֮nS _P1U2=y; @CHQMGuvʭkΊ^MǛѪyEi"U !h|ir-ͼ% kGk(f by+)ů'[TLVO^*rT{T=84. O7 y!&TM #p"7&6H72kk='Bl %:w#hDe$,ĠUYe,-[,fOqdʸ/W@eOoL^\T:_ 5XȩJG9} "/I|"c(_`.yp☝d4X)K¥ݑrR:c*ժ<1Wy''=+.Z uޥ0Y!'&3Rށ {!Q=wbTBWT^o+_yimo&1%TxVT}o0 V *Ajr݅m)'RjT"eOL"z}Dk"ݹtɟ4h+R'ݥ.fxC呐,AyI(d#*#lj@$z\\\*䊽AX%l}8UylI|q,/y{!} v&~L<212Č"8RWRQx3zV\YCtJ)7E O ^q? @zX7 @Y_D3_w܀;_Qw~!rx?^dEfZkDؤbcQLmՎ4n%qJ68)Vu8%XPd8ASc&;[qEf6%i77XܳP`HBJZ*":O@%Ql2Q4Q`S'ĪYlaH`^"NnihShcsf +ެqbB{I[ۥ0.M-VMp8E*|FS5^kye^ĕYm#VL5ʯ*hܶsmw@I3peV0@=i^.nĘJI(ʈ)y Y[oS4j1(+"WPgKRyymx**A,ѫHu>CM9 .}cB{ʃs,EF# b92 'X81 aBoR88MLE)RVT+@;YR`deD1jrchʵ#d ޸Ա)M;'ּyʘ-,n-#-%`[~h \U5?z`X4ްwHEj,͍u4}xӑ#I*1gmĨK2z#?`%Z"QaQ $&QKDA̪5WNHЪ)=x,?$ &Ϙz,*N%x"4zY9~?QiENQfH*=%e8Nl|)ѡ258Mbm 6,=5IC #"/ R ~Hu5 zՍ[tdsf*b@DI]1hЩʫΑ ,4J6n!nX^Ҵbس4dpY+^,[FbJKy^^N@E +*Q,m""Ya\~eWE)v\D}2TsUq 0 B}>Hz:ڕ%#KK,'8$@BE1@!.uscF?w5D.fD-{TG;PD@1q+t^T!;eb%?x eڊ1y%?6DK5A/D.CPН8ކt{*x1HZ!YRxtr`7gZ;AuWgpB˫򂢧lG+xV Y,=ܠ0UhrѴ VF|9TۙáL F0Oa5>D}Z4D<,BkZ(Sm{V|ORMUp{5(r-gQH0es iɝhqYW6Ԁ0YͩTݨ/! 1`pBH-j_С{H$)i\Fa&:NMaKb%_|!]찓/(%dl'N(z&m 6JUniL{KvFE'S4SCՂFC`յf1uzE:/*zIgi߰]hy4PͬY kR<_LdC5DQ7 d+|DUgjXfPi 3ݜ&P(t|o fo5LM48éjojGITV?gj#{br3YSX+MZԢN47S7N[eٺ 6̞yUx)]'{K݁OO#پV%*/ot'_Xzj d<\㪤Y0'䍵@Qzgqz>%SNRNL:: 6цt  1%U!S;0 ޢb_lͳ ndFt*gVkYB\6{XBK ѽw8ZW'_v]Qm@s@F8-QFQ?{W|23r{3|efy|^v^9_j eơ!8`K+Wl g&!9sl.ea}iR a99mBQ$GvO) qS(k,h` b4c ѡ.pYέRt|"SO_jA"stN~NQfYX:2/7KAڞ6uf49* "5ԫg GOsQ)QYz~L_0}GEL2GBaxz|i1): ff)Ҡzu]̡mpb1I0|C^VE8dp0 7ė+q*)yхyPo9L' <C~J (oBLvR~:x-!~ԔױErO7Kh-P_ &B&ϦZd@i{<3CUM"(Zl#kB:pLc2:EW˪"L(˰#))baSHYP;e[8[v5LH~]-QY1DhblZ)Y^%OwX4& U 3Yr)ɍaFX@H[b ª < L2lgG'M{Vĉ(A Y0R"s.XIgal˃)ڶuw`Έnۀ6$H]<0)k*[P7'l"ښ1l$<AG %9JKu[꼡!H晧bД*WYa"4a ? X')[#9v[Paؚ)~oUR`Ţ𯿊]Yp66Xl[a lWq=kf{V*h8f29\8[raøxI:󉎗 xx,0Tjjc hBOFKU -ULܲٯb6UƓ}÷\$>S{o&؎lGh0H t -/#b,5e Uװ'ƅױk L*nf V3&j-G,u' J*+ֶLNaj-}!NE :'*J/姊4xmh] eZ "J;x|Q҈Da&"Nwuy( T8yq;vZ|A貤g!z/pB,4f&r#]B$3 O7 NkU_Xwc\+@d.8t %qqR-CKUͽBH 9&Ӑ0?i]J`( Rr5hg[fRi|φyʯcRN:L210a -Lo<&=Y6K!v#8$f2q+(i'9#;ҪT bȩL*T֎ؐGBpSRNG%(6R!+TwN"3 \{ _01"tO^9=9%&③70|"騛rKqnA6.OWj5xbLȪ=g2/z` MBI4hD)8%7c"RD~]0uT-<(VIT27/ il4sSoL{Azy A< г|_*ղ6pް̛!NGc*c `Spyϧ`Ӑ4FPuH@)"c LNt(ç WG*s122浄%Tfo2P#>L=TYφdl=ǟ7`>UHV3]i~:p67͐DhLz }HqX quaMYi<# X߳f(2S##PV0eu%]/x@ ~'A%!kd\ pl( '\K4ՅFG:dcɿ4yz)ʜ&tc2bnnOU]N5k4C +*TATt)!\CYU m)ymLS]eK0G+OY@5؜l"'CWUr=V!~$cN ܮ{"%}B&i`!4tOCcoq!G::n 7Z=bWڄ⹍~VMe%43)02NQt NǔBR˧KLg&(,_%jGDylH=^C,=i bR`O~{=GOz'JW$]v@Qр(ضSN>4)YRe#mE\x1 ?EkJ$"Zå_j+XEy y_$/B[=UNafG>.L'JHu䝅ϗ :T>,^!P\Sd/m2_?KNDHz|EurG M6Sbo/ZGqT5&rAVgE6D;.d±ïQƼx@LfYk ĠQ*bH-874xkD*0+- Q[X i~8uvdbS//R6r KU]Gmpwƹ ;DhWj|&dCY%ܐ(*ij]a,Ee>N:P S/4lԫqx)Rk~jj>~CWg},ԧKAxdjk+D6d+hPq5 N6lΉdhQ?Y$_ιDc!27Z/!z ^VĢ46gŠ w_C T-JNb* BKJnNu ڱ)[΃1,h#ޠ ,̔dyTXN$r29P=0v9:RPIC<$p2j pR$ӳ0^w< <37AJbWLneקMfҀɋ&ņ08FCy:Ys<>Cns = l3 UzFS^s*"՛ VrZ:$Iۉ63[]%.Ch@unx-~;Ď@ /8f>c ?|:}x0AWhsS 0~=4y8_kXG h}9jdh{ c.(%ZɸiS| , :^w7+62M!K?8Nc e H<{4%E$B*T&SW:) # Ƒ1dYښdWQh(=QHPeBd@Fx4upT 5("UUDWBT_ 9\>1FwPQ! 1:F(*T %&}m5(ٟ<ȋ!sAI|e*XD%(G$2Bb?j=~1>j -<"Yu)hl k`͂dE?D[qaW) F`'G3شt-ABY<$j%j49#؊6J&#AD96L*x`CoOT,*4 ;lڣ3^2sQz꜅% (M݆TًY@6S.rZđ+QPWҠ:We1rvZ؜Be4, zurSPhe17QKT6"Ppp\⾀$Xg>qL.ab)u$7'(wsLA^vNu)(2Tz<,,*m((8y4cN.63B dxldZ/(aJ pf (gtN׊h: kwQn8L\,\'腶0\sJA)D*ظmcf*ɝV=^S\:>Ǡ.. 3sX[9Espr 3slfQROWf7,p9a  {~B)Omdf &}>)p:߅_aP?ms|bfb`-]Tm̑0#-6!,Qv9&Ws6Y\ `g[u랑UфRXE ވɖZ}HKf/{7?r9ԻWP-;$Þ6r|q*-bG oÖOsnQNXeg HvDs|%T^;Ay"0Q%:Q DYyߧD 661' ^'];H&!AslҰpPeoꢴ*H]H!K2[L$vke&nAv<`{ ]##h!P5~U xcg fKDXFIe@ajN#i% ZCaQ:R'4TkdYPCdCؖP@ goIN!2̶HÓ%vMq:3 !Zۨn7؀Ls)%[dHVݱgQm ڭ4A(T@%#XYBQ(Ԍ!ϳ,Q>Z+[O+OY0 Pj6&F#l@^cwcrf?\ilY$$d ރQ :w$~6]o]^ 4&{ h`&|KQ/JYdXKƆ܏tQ4gc΀7!<-Ǟ S ф\*k/"z`8Z@h)`tBEf@9S> Jx5aLcs5p\P5%N<j[HsJ@nB !h`*tˆe\P#.ٞ'ԩK 23EOPU= NXNa(dpb|o?yL ;1T ˁaR5{]hv6bϹxH%yU锕hpU1t0ҫ䘌bv)T!ARz^^\w4`Qg:D9}$,0#[8;\&v h'G,^بkeOUA, ?7T{Kxf]cof)}Q9Xe~.ie ӀǨweB3[LWw UpE>`F;|zk[=9ybpۂE>@X|i}GLK;p({'S,ƞWU}3"驩qչ=w X%v`(u)ȺvdHsS:56kK'\~`Q7'"FAԔ .õZ깖 (dP(6~QSvOȀaF]ۉ %Z\7sNDC P٘CP($sbv=[rɀkgؙ zcn6GaT XDފN&Wu$lrg%Wx 1UnLTĶ4xpxYOpyBZ {+è)CIROJ6C00 CEdg;ֵ~%$"LLW9㭈@[AS4rM55{:株'b:>-RWQG[ jFzj]G+-Gć hT#ěfXA׻%e E5a="3U'nd5 +Jtb5|%qNBJQIj9*dWUIdCW 0f8?ID4C2UZ眗Ou/,b8m+* ,6"Syimo&1%x!!&=.b>_P>"~"SO&'BWW];&໧|/UB%5pR ZR%i+R'ݥ.p QI xc KFNB&UG;1~'8 ӴGjGKg[QPK>2g՝}8Uy $G,JNQE"T(R;~$hPY+.ƌvtcml>]6lfcWHns"\Ĺ(Auim!V͉tJ:Rˁǥ~É |ސŨ,G1u@uT")rʑ. :v4<%`6>M2PbF q aقM[t Ympeu^])7uZ!^q?)dKޝDAĀD$^<{+0ue/m!QE.J'E(5Bxa' K@(B I)LD: I7I :tTlL}R픫ő~ ;U XL'%FAXw 2W\2(擳%!pE6햒)lA"]59ЈNl+<$sRD1qqIv0鉏ⶮJ>QM'B$J;JTo r$Sb#Y/= yKbB=h9aM.M-VMd¦?N g>yժlD_I#"!N/(Idsj ʭG?]qRfVպRS֘IMGŚVafυJՔy՚=1P pfDŸ хm83ZAW,{ymc*'O>)F=U i2xS=0׽vGqm* !@Hu>CM9 .}@*c ZA""# b92(tj|:L0k׹qDE)RVUQ\qɑw*䬦k/F(E2Fo\րئG ۃWk<ՁhZ7&%`[~h( ڪZ,%-X4 a%$ҿ"5gƊRҶ9r$ ni&CXRm)0|IFoH]w-TEEhK"˸O4$CXC+'Ȥ%}p}3Q(LD;N=oT_DЖF^/D+Lc E8ezO;B!2//xjN"=~ĸhl[I@-jY_GXO )`.`TWD:D՟mqV_,-@gT-,oCkDU;Fq䚛":MEXC\QH(\:o#:]ةe*, E,T_ϑBbB.x6Q8z5Mn5/y=eTt@l`W} @A4.T$+ U4ߪyo %.+Wz~ߓHQ[Fй*Gȸx%MC}>Hzڮpʈ%y/8.Se#&(pԢI€Hިscwubp˻Q0{]X \=IEp8@9B;źjk=UKQWz>CL']2j,$fmA/#J3VF9xҙ >F y:vl&ԕ.jPL~\FmSLG_=~r.ʓ52y4!t}qPWHic*2J2/,S9<)ht-906dn~ M_C T/gCWEDg$>-Qz(z\\O#_/H "?6g]w|;\taekfdtT|SN0K9H?#!~~-')-l4&43 Z"'Ihv@*м$451y)NhVOhK[R@>m7[\ [?o ~[ "7R@[so6L$w-o7.l|!7|@|{E7{8=,\Bu7nyC7n6Ppitz1B7 ,y3@7W 4ys1@7/Lxfso6٨f[m62v7mi8wKIo r%0-nv3Àg7 Rfnv @[ t|usGY7_T7Mlu3NIt @dK7&|tE7, tK@ ~n M S~ <+>%6 |NM;,H>a&\n?~!~ö?R=@"[OWlę BgɃt#S@LvJ$&ߔQ)ㄢyYtpj[Mc+<8nG=DMk>]e*a ^╵UGTwibh˞_J^~[ (L7 7Pa*鱙jTp 5EvZ0 @ dHҡ?$::BC ErcWYryErK *TT蒐M$)fJBQ[rc[ÈU_V0gr/$s9ꡑQy*-B3*,fV0Tl]PsI's!!5fx{diq.Kn>xJ AI6Lb#g}XFA>l BFFJǠCAQ6F3?gt^,˩H$ry)Q ៹ņub#>+DOɃ{9)G+/-M4 LM뗑q@+> /f2/+EPl kXqzH.FyC wR|^6G|a)Uf ė4"8P=LʋH( < pD'DFQ4ƍn֢G?zgRAuc|Ij$UB`V&UWP}2C:B\Y2?s3N0$Oa(&}P3RN@R3l}抙*vEPm;qYmyj͐, :*FH2L-r2?!ʹAa#5u, P+ͺH). MTO _>!Fj*⚅,+qJC}B'̶%&[Eƨ/,WȂ],^ :f#쉸4H$,Gջ¢^XgecBA!!~f 65\٪/qҨj֓wR2@50 Hm5-QOH6P 4,m^ɦ,<5ԷhjU-9ϥ=v]w>k{^esT8grXqLȬ1 EEazkhBq̪`/j|bϜ3.sNx'&N8I|bӻu>k3~)w{NseN);S/\u{W|}^<] 3G/smux]NBq&-j; ]ŗOj6`س>f_›6|m_fs{> kX3:[וҾt9=dq9~^}6 7$xK-ۂ]Ý{VmZ+aޭ.O9ȴf ~雵p ____ťVLhao}#s7y}p=N\Ͼm_)9cFO}wm~>iI1eVՓON}輶^qӱ`O<S5~NOXevק)O_|+T3fQ7+G­Þ|ÍWN{}ypꃭf]n>YW] OxpVmw[7tI}۔|}[.k+>Mm35ewOzE;tdvL3+۴I6'kE|_wCMU &pogևv|xߒgu}aK[Gp/r+&߳{7^7pתgG'8VgOiאI~VAO :zǜ w)ɺY%o6_qԏ~;׶\zcBu C7shU9X^Ye1 צp{ɝg\QaQO&|/^Uߘ=c>;qFnoߓSk se^za! .yo<5\ʫf8Ɯ^)aU5'~ry ϻ˶^GbTzf>x\/qkugmpÚ=?~!dc=N<݁Ϝ55a9nڞn]W/ؽs] +2?{썝wn\x۷>RxmYzV}4xʮq55C֝x3͕tWFMrWifoû?ͼ~S''F(ᆗLxqqPA<~?}a@n7޶aVaw:A}x>V7z)'a!מ:iv>]o%tIk?uW{f]/gݱ>2:bWOP|e뵅W9ޅ}ZwޯUki'G^rn|~ɳ*{a͎z?rȒWfn셂#/Maq 7lO[byһg;?zqm|t=O9bQ OtϯYvԲ[j]fvҎMIݓՇǾޱhWޯqZ+S٧{_7yk7g>#Okz{ tl˺z*VN9!Ո-%IÎtN|[)I~k=?<ϮylFΝk=}덙}O '|i;o=ngɟ=~*KۻǍ6U}^ɧ֟jqK>//޺ק+u?[=r' ~7uy߿ #~;ϙI 3zN8>5u=ƼүFxܘPtpҞOXa?tҟnߧnⳝ/6t 6=~E[Wp-. ps_ۮuž~j5޻y|*0yJC=;̎ۏ..䭵.4gdw}/ٹ!7ma%g<ճ}/P8ű=>Z{?tyTo?%ޭOHyuྩvY|L[,vBcmӺ/{?]Zp/^'~꥽fuo̭~ဓ\Ƕ_t6WN8,˟"4#zx[F<7;=WI;Nyzᭇ~˯[8p?ZwAm;{e5opoKOa^Ѯ;Ihͅ73\{_v|ڴzļ8k2k~a7ݕEzXuy{~A]aޮtf}EZuevl}{-ps#/̽kv?c38KKziMއ$Hn/Pe~༃7ߺG-u6\vSۍC]]/l}I;V;⢤U5>Is)G^spm?ԟo.?1/twu/ޒ屹:ON]Zom֮uȒƝvvTv/)p]~~ÿuf'a_'[.\>?:-zWvǞmwnIJwI۵ Oy -c^;dpMڝc%O=%ccNğ{>2)mvsG1~γVS^VʏGI>퇷Oxgoc^<<}N2C}b_ug]?OϜ8?z}r/dv~Moii?$|oF;-]/v-K> =lp.{OƲ#lop튱DOѻ C7.۲|\껷5[ﰿeػuۗ/8]]G[ۮq]}B΢w-X5SKz{+]NjآzvLZ7_>=nrI3oӻo<{;9;ۻ:ˋ{-M0Ś*]mfizZ8>ϓztG-< :rAEgt]V~oa+A߰_:Em[t߫ꚛJç|q˺oG_l >{a܏vӮԻw~tW~14}e[:}^pѸȱ^叿6AyΗ^U·^|=']:[NZːn#:.|'_~ę{6?i7Swҽ_Nx9a%8?ǔ|c?Kvݻ+|S_s }iϝC֜',꡹:ilu[ img?>BWd޹~ƸuT[]-'D~9Y7}{jׯ+?"qX^Bד}7{÷߸Хt_a{>sݲtXFƲ1_?>o8m&rc[g+O玛ͥMwG1A,{I\VZӣs >Ay #7}~qzތp᧬>_O4Ƌ_Vߗ[qɾRƻ=1!۷>C^z携_wqOy=܋tik>A _7yf<}هxmϹpo-_7uܙ=+ed$Gno^XUiJ'__<3n+oӋ|pyhy_hwˆv{mhó?q/w,(8wk Wo^p+}7x%kõޮcϻ'{*ߘx>r9'}wꬍv}pۛiQwrޝ#ڞx19U?raЛOA#nksN{ *y՛/09+]wo` 7=୮nܯ뻟e1{k?iӹ7:3zn~;5׈|qlk'y7 }w]YU[*_[{qE[6*l;PA{"BDŇƈֶik7[mm֥ gm]k]n7čϙ\H~_/s̙3gΝ}ayă'v^woiSʷ"'\J7r7.Wv~Hkڽ0awM=]vN+)=͞_h*RnaSN}RUN'_fhcT~ S^<VawWO,X-ejާ͝]n~n|vcuWӎOf^?ķ?K|i/x7,r*oG,I;T}sf{gϏ{ޯ8*69^oTn8>wqo6|])_vW+W=8Wp 䒗^78ۛ5qKG\TߊrB{NqvuƢ]iGuZ00i'yav}6]ש8u.O K{fэIw; zWw_:z8,a@y^7ꄯRqie[&~z'(wfOUpZE#ˉUg.oq,zە[8|Kem/m~Y%_WO^;m~>^䣍o9ԭbfbǿlGFl:gʞ\ౡ Wz=E꾯:Rk-C/~-ߴ%b +O,yjkw6?Sl2yv:'ؖ7i+ݛL;l/vMΛS>j]+-G$FճϬxC\Ϛ>_׼Y^33Yx4Mo>zѢK_u9d)U]`2/՞Oؔp%w.ϴ[ǟ^0nɱ+wW5aqh̫Luh&wngkwNi3zdڏZAϵYE7;f_rɯ^%ݷ"C엉V7޾ҭ/=6n""Ye=nI}n; v߽won{Tmu2jB˝kiom\lIjv5KC>Ĥ/{OI;?jigTߨyprrq~WCjVaBWzko53'z;g6K݆oy9g [3״Z5GfM{{#{N2/۞jM{4}"[O/ Y]qgo&-]qhѱTuK~M?͊o~3 p5_}VR&Puu7y%7Ϳl@7u樷[i=opaێf/J֨ycl罔-=> ب⠾go~W-Cj^Ll?:7^}Щ3] ߧjø{߸l`n^ǧvvəN5]h˛{L_~&Z3堧4Tz둲Uܹry}If<{?x'ޱ><A?s_軵/OYt`;߼zkӱܮ7_Sy]rUAﵟTX"}W'^lܰN/YS_Ŀ6dGϙz`фnF.O- 08ڿӶQ%~2նo.9쳀U;-5'6yrʏ]0~ўm=3|ca<^| 9筜rnζ[MJ8wdsw#u|ܨOܿ[Ɵ hx7,"+) b 5rƇrsKN?w0~f$:D듚L!Y!&DgfeԤ b$O C1#F.o0CøQqF}&EH 9ge&'&@CxDe>5a1Y  lq\F3<+8,5_|+OX;_q9~><{׸?j|gϚO;[bw}{`kWd2;r_T s2I'@#@oDdn\>p?}јB|s;2\+}n'"Kk7ߖ5 ;-j*zn&zV_B9E[=h)Ha d}H`ځ0咷~$j+v6 naY>- ~ߙſ/7Qy~M[kQ}[@} m$B߭ ܿJ_{60x08=9ǥW{qg2I<͞#?Y8Zths1)fKN|Xl5)uYtst 5N ,&;;1)=SgI=r #9ޑs9l1;=A0o\*3sesLψhdP!N?*J2hHlrKݠe [r #;Wd/Ctoyzz3z؍SN9I. [zp0 XYx80C>nL^90vz5 !;aZ a=,4cʡ O;15 A W|0os/Q36aOzfAq<*ť?@1W喂G/,5٪ ȧN/tP#D5= CT)Rp&ho)7T7-( Po؎ZHh+dg6 A\YdE^>M?^B(ssHaIғ,#Gs)aulgfrDS(\/@^ƃm.cWn|hQޔhBPB6ҡ{\7v᨞gxG2dvqp{48g}BR;&p[`o叺 %6v1EDwȃ*~zW95WDreϘ.4BPD?)e-`tخdAqFV Dtn̻(5VW# w.׋56o;~ODkRoǻn*%+ Нn;9GtGEW&ڄUKJBL8:%q?!n2o$?\s^E]m# 2e/lTV#9>YQBޗBwFe 0 ]DӇb;L7O09#c^$$o!]tm} K0 ='n_A p  Jv ;:i9GAN'qA&9;sAusO<0]K=S{+ǡ2+~p E+7h3<\9Av27.UF$&bC>Gy*e{r6f=n9uss=D {n{&F/9`a5 {D:F^7=*I<8\$&IK\TT?z.!~x:AO=D"""p,쌬YI:%r9ԥ[(7*֑ ICX5ٞ]bucI" Y̔ =Q!F]vΘfʜ2+ӍH=L=|hRv[۠]I+Θ0][1m:nɂ:h%Ԣ>-`%{ℸ,.m.;Ȏw#[Ւ-e?;o>}_!dh/nHE 4VI9V;cr l΍fx Q^ {j=^c.S9/ cI:XVvB(U4Y5-s~_-ŲQX]m|pނi BOɃsK νX(~/sg< T%SyDe| _wr^L?xvr]E7}sC^θ W5E>oti_\u~(pӧ3uʉk#~ޏ[i&f0`rB?<5 Y?Jsuisu3_:a܏4s?9 eN{α'O9řyxCgp= ɬ&UJ {iuB[D9/Dx~Dx~[/>&‹d/-‹E]+‹^|H%-Q嶾M*+;EŽsncoY `lJk)o!]dJ+cX7 ! y'W[4g8l;NvR9R>ۣ!HZ]qu᥸7֓txGToóu) ̅IQ^_5(&5WҌ*h!ZsLŀS.;Q+7LZLfy{LH\& i,4?Qx#Z H&$6L819!Uyqu)>Ō hqZzxBܞ|x)T=)IR+¾cR*Zy 8c6ȉ/,:A2s]#5<[x@fjn)gQ Z/0fVda3y'դbh |tpƈ#L7qL~q,dET? —@"&3}$Dsc9Y; YKh|b^pk&bw8Ev!~nx_lr { ^\%9JX sz KxFv-Շ 0wb9S  š@8(ȥ0 _J=3,3Y(ByC1Xha/o]edmn,dpNda* BaGDG#=($Q2ɱ kJ$K$%ti)9_kaW%B8_0Np$B]?%k!v^pm%{!c|< zD{ItMĿ0n7I8sK B9q  zJʗ?S^kB(Aa/F>s%q!~A*?Is^aIzaRU3-!"B6u5z,IjU$'8$Rs˱Hai{I.Is%B(>ʷqz)spRX4*$ UlR* I$Y?I$0Ns_9,YV{~/4KϻH/ݸWl`81H=4,dpwP# |NMxw北;}w=3>83^axow7?vSg|V?gҮל~v}onGv=oixF׳xnHqocNOMm਼7lOGxFJ߁i=a;D|vcJʝJ b=$,hGW/c$~VIw'ܭ*sQ.n7m~uoI}ʏ\Nƿ5B".Yƿ5訋|.^[ip1x[߇]'wbƿG45~xqЩ_FSrMa&ёFOI'M909}Ir+Y#!!>Iz qf a !mgØ32*wZA3_vQWR ;5?paR}:߸"k07E xo\Tldq2NfxW}?gp W}zȜGC?$x ߌ/iP6ޱNJLO(Wr޸' <#puЌ p{;~_x>5;5<7qcG]į|0/*'B8qe#/=!Iop v]x^Nߐs$Q_(~"IJ$./*ǿ.I$&7IүO8swJ~YDKI~c$%pgISR$p~Z K -$+ܪ j-;U*J5N/>?)1H08X8eC@bILB. u9t i\ eg蓍_FFV2GJN7 1΃YKgrk eB Yyy@ |sr2tb.eLh߀;4^<;rnj>sV<{:p3r^ b9 IXKgR\-*g˱3آwAa2d grz2*fOܜ%u> z ,c6SDu9X-yeS~9Of3T=QIƧJ g01 )CoI1IM!b^»l.! ( }`~8k !0as+€!,*&c4 [qL  C`30a!LnF s\.`~İ#̩>q0q1TV1*OrZ aî0b؍ð;}a mV {p6 {^ư}a0Ǖbq0wC0 yCXOaxc|zw:]9fLaFI(AiX!QpJ1tEJm/kM=(YiF K[NO`bRĥ%'0J^R}DO`ĴFLIO`̴RR"'0JjZ?QbN%7?QxR$Ր%:1+I˰.&p_%p)גGx+בGx7GG8G8I#<[I#@aH#\cwI \Eԟ?'' _aB͘cӸOr\ĴU^Z,CKbxg5dÿ:nB ]b)RH["c7n'/Зչ]$ wGhHH|oՠ9SKfH*T8;~0@O|1u![BFq&._ Vc/)WeX,rsmB4B0\ĥR0T"q9m<Zg,+@rEq'. r"#wGwD)\g"|HcNe2= UĪa2UFTjHCZ׭<(1555D8M3)o"VZ4^=.G?ӶĪ;vuV9 B,ȁsHub И"q4W+ Q B)P;XL9tDb)M49˹~CLE8٠I16I“iŋrLp"3o"x}߿ &^BkL"H'9,R=9-= j4uX+ @h7Ϯxuj+}|{kGP'iWe+ߖ,yDW~ h"amnwȈV rǎ<]$&-K8%yދ]k+UFGl?5e&W B߲ MUzi+h(56iblkP0њA6j'lrVw?s i\jy37 =-IRɾrT#RVAǭqi0N{&_h٠|e+`P\R ]d6"HEHD?Ln5HX,M}p&֛"}0}*j2>ќLf<BMMa\v\N%-@'V4'A@v})bxCz9w4Ixt*\@C {eہ3H"K"$pH8XXL 6#j*v;[Թ!qc}(gP~030>O 1^nM8MSX[okknм>HRɓAYx8[;{75dGJbu—  {  k8tz_ԥʕ3Q,>4̇9H6ҶлHYGqȏ/6XoҠCO,wΆl8՟$sǚw9C49W)ofdlYh7?ʕ@L l6㹰e]ic؋]Ā+yII%9{q>;iE*UɒA$%m S3% xh'j)#DYe^%uOkK3X'I R#ѣ:j8R P{)wEE@ǯl/TZn~FkiLqV퀢dשM(I3DvtIh"~3, 1Va&+m[m]P,7g*TЊFo3 W0aV;YyAVjq+G.g>y&.8:юw1 /e BRIyiE2pZN.1::Rqd?AT ֫ej\`ѥT)`+_6=+ 3:Ԣ(ٝTpߍVXߢ/*sVm}J3B gʲYjXh܆%T;JfQ~nF5 /{)PnoiQͫi zQSON^N@KW%%5쁤WYLth#,2gZPNk8n&{Y WF6BG" d]d<H"Eow'\o GB[y0|W.NElmV+?@]hS. )+ W(hJZTCWyD7p4bR/nl:h.L>ȃ\Gwucl Gv|Ӽz\a <[^Z[.'wU~rc0<iZ\_ }hbHS;d M&"Ou"WP59IQAϱ  !^f kO>EY~œ!M|74#: 櫭d&҉ eR9P ʨf4Dlg'}i'esO:]bMNQ7`{{T)%i%&u1zwiWr1$.[a Zz*Fg.ØXjHQp&@C`)B<Q{ ZY-ȣYԏ>%I-,=hPI+O@7pA],:DmD`-݋bU* .ڊW Xc\'&;8. M;hlIelUyj_}G#uS$L11?W2J߅G`t0j5P^]AѻGM7TշE< )Ĉ[Q\sWt2<_'z_1#>>E"}[ s8)[!#jq2,iWD暥P |X=>W8Q!ȕ06m0x/Sua7Z*1#ȸ7Wn琙~Ix/C^^Z# 1SN>P0u.9MdsdaFv3#,E#eB֩4Qy8-a6FnYbz|"0 | U,ia% o+k5f|[CE&/Š893RD?X[ 4q ު-áet9gΐmxr8iqu q2Cg,<1~3(d pgFABɋZqIᶉE8.dܒ+LZTQVԽhQ"#p *e*m fNd?9;LJY|Xqil }FQo0r}r)*1v Ȑs ;,OX!} r`&j^V>&iR ikJ7nfD\izՠYCءA RgBz*#}^QG_)!AI}.iFc HC荳r %:) MI7dg$- M r9wWIAIC8lgᑜ]dTƬ,UFւ0?dД973kAj`HJ3r29)Ԯ)ӡ[qq\V3jD7nf8.6.!pcōoB.'+EMQ@Q?7JϜxij3䑤YliMsы+=X2UYPyY9 RiAI$?Δd7tM/5a$mɓMPĘ2IPgH(/=s~RFzIEw5t7es`@T3YL07=;mˆXl\ITLʄ.Ux)\UޘJ?YEk2;zDe>8BC*tނl.dГ2rᆏ5z|#t q8-\ Fz=B>NDTP윤yԬZM^ҷxRA @ ST AO6B4j2O .P.Ԥd@`#́}56t تؤ)0rTrB< &9 8SFIƚJϜaT[:JT/i!jJ1#T{h$SQ5,*>Wu7]w@SUDS' 0p`T-HCgCuYjx<@N Y;IWCMU̙G g TT!9'=lIbx`WC l;"qa6Ͽ*|gMz^a*(m)%bAf<`R]Xa*jpOm0GgJJsQ 1]dTU4 R 5 UXI;6iXm ގ셳wA)&*)!k4fFjh!4t^R."VW}t^VdCqbklhXk̈́'';wy Y{|9m8m)tcQcp_M\nh=z!h} $D(t\_17M)Th*}r(Q^&P v@qQ\.^q8t끂\ C:|Dt+9W]iKE] =?FmD2'~HOH \)˯$?h cȾ  Bp)G$p}_m{p7O|KzThOgOx%)omX7=iIy\Iңos o~@OJ\ *_+G\/gG{H Wޓ+Qx~(KH.7I^.(/J: r2k^83%gde \#? ٧OƉtpZ,A:;#Gm h׬\Fl]~>_a9[G>OCTE?̢:r|F9thOK(45#Tt1Y~$4vsd 26K/ ?j:j˵Y\FHqkaf]]% &j̖QtdKmA~c%CUzəuDCb'Ơp$h}WX㵡olj N!tidΜ5|РmCOߤq:PhAo'w $<ߤ#Fޘ6'ֈ61wz-wvZn#'F2rNfϩ`t:Q_Q) 5qs.֚cx> RvC0V'&4ڊs=>sclFfJL+S|N!u"/tb:Fnj!:;ɔ $SDj.mcږBlUaVdx[/l@i3vۄFcblc(1ңdDP69d @ :`ZlL@Bbzۘ$FN28vʼn8w |g##2w~}#BnNP{- -Ds8o/EsNM[|w(/ ~PoJ')pN-|E~f:_AM'dV1*I}~Y0ŊB 7()B!,o5Ks,+UH 6##V΃aA {H:ٿ௷\kƞv>^uNe~`m7f\˘]oɅƋ~ z .[]3^ | 9xo|%s&>.} @2.)rA <,wA仸p-pA_ܮ.S]wAM.#]Y.]j2W"..\=9}ȪgXs/G У!|;R)p^vop؝w'6Kƒ T>qnB$ׂ<BP|@%‹sa"E/^wFuV&#‹M.fMD4^b.[ᛉ"'r^)EZA믏Dx9"kN_*·mD*^/>pNE"|/['wṧx+DN"D"J Dx9(-w"|w~(O>kfsFi"|O>[%"|"/>gEx^Z>\ ?[Ex񖋶BkHVqZuh (/m}Ak,ߣۺ",0aT̟Co5mϡ¨ ?.fԟC;Q1-&'?&#̟`(ژ?[Jc s800WQu1GF9|0*a?_ݟ>F%g.ݟÛ^F5g6ݟ&1?n9 ܎sp{a8?)w"g8?a8?wz#܅sݟC՜ݟC;rv-94A;g0A9<pgp ݟ{rv9p0gpC9?#ԟn9?/9|p! 8u,-i+HPGs|ΟaNE[P5_\6zq{gz F1B;Deu@5ז]UiM~7MԞ#~ (QDa~ךI N`IBv/sC CCb;b.NLo.1a0.>Dw1]^`f4Ux7-YҢ^ {ɣ$.`v'YT<Ր뗥W{:-Z Nm\5/#ݭenn ߏwq^ U歴bs4)H6Ҫ>%)dbv1PA `]s/烰'oBsNDm4tӠ&ۉ'wf {XUZG\= Mz4GH@Vw?CH?^u֛K{HۢN, B>6>o. _ɪ::$n@_ʛP}&՗jKGzrsNQSdz'N>'>~ܾTI;V$i}tRL~tX6Nz0=]=28&4G~ o2g_$}8*̳kT/ 鑛!Ig#">"`Ġ_,!sM=`j"tЅ<|nXkP{94_Л?'Kiu#|4f̊& #a;b pǁuϻ!bH0?Ԛ;ыĵꔒ*A۾(κ ¢ÍWr.,WH"IP~.NPt(X%SA`C1-mGb֌jDbA3Vnt 鋫 Xq|6|:|J5]Ӆ]Bsy͛(3h崤vBrX!W5cB0yq_ AWc5px@2Æ~8\ua=7 L4?Zش#eaMZ&c\/$~uEzP'q8@Y}HZKhN*:+>Fi;P*}>|&(җ >8RY.5 Ź0n @Um(k R:ӱ _yԢDɯE!|SC<~q]!P`",x@ۈ? ;dV0}LFNDÿ )Q;( 9;[MZ]2mB2 H,5C^2| tj`ByPN:uX~LZӝj̓?]ϖ^]KW EeCqkbU|_[JKbj{*_{ 0³; 6|u^G\k/cv&Hܧ6@CC]MD\ص4cxVJrG&2>ljLVaVQNZXzz{h^M0f^z݉f`sz3o@k?Ǜh̏ïx% pphxM[Ћ9 /9y}ܴ0qK3΃ĿC+Θ럂-Q$=PMw(/\矆+{HowSɯC 땫V-p[݊ :GeAN ھBB~yShjxEW"a!tCX Г/e9PXxub>> }wUc՘5 -1ގ>4U E;U;?"?E{p|b|(qxQFLkxMUWCFxURK./Jq xiF0 &v3.'k뒹(W]}pTfTRt!  $H,BWB"V(d "bJ'a]c:Ǫ0-RaBFV5({{9~{:_ڴ:;'٬3iB|zdk/<)Z'KUT VSɾ | >eGW^lԬdspD_=l³Y1a~6tE#ڔ3y7{zV:}?o|`Nvb(HUOƗlbJ`W6`>''xpHPv {rG*ǟ仳C`88jSy9>-[_|c?O2 F`p?Z{55\6sNkO &&fE5LEAylBy '4;0/>!ZRMc@T=ȷ5lA5Ns.uMD]^%zAq Mͷ<ߵҴV V 9kZYä4\hJa8h\kJ6r7*S`w )!nЀTk#+.FVϟRwZ7_37ޖ펊IuM/B1#PCm{xW 6h,`_Ӟ`A3Q` BZ.:+Bug>- i-(*uRךO|#*  p {GjHp5$\ Wh| _C{׀W{4֪Aִx,j ,1e/ǀ\ 29؃өi,jQs@Ľ!Y>g>{ Ȳ4m/ȃk׈wkZG Aox k@nk w< 3265=Ԉ;@}izOrȬ^H2'U⭨8dijQ]s)wg̼f\c[52p{SySx{!ԦMɛ#0\,@f9x>!1= ڃO26"{I?H˃6Cn 7Ȳ]  ߇T9ǒ797'a91_),sώ+&?i;;60k= Oj ڱÁߓkڝrnw΀~$xwih@+|)-v" ?Fn Ŕ S26CTt}lh_opo0Od|]g#J8#p3P~x$~ (OE?DbKAX3p)ܿ@n":>w>V^{?؜> }Wf6BZ])$s(<3; B;IL'Ζ{#g)sE]ř t?G\Z(H鉳7iZ⌌d8C`<;~ tx!,Hz kaJR!G. ŤѵnnW\ α!jN$S=\^Gr$B$\Br-F|N$$K2?Or$B$\Br-F|N$$K2uOr$B$\Br-F|N$$K2U"\MgU:YUrfgbXI!]y0Ή^I?Y6a$}9>>6 ^!ٟ$I#O់iB)Uے @?QR|1D(ϛb<#36oÛg)J|FN8 Insc=tu|^zOҗߪ_;o^;o_:N)KI aq'x}5D 0Te? x)2Sbvbkq.h__C8\e %9Fa~r).:i*ޞ?O_w/3 ?M1 ⏖py.K]ƾk /d~>==\VK&W|jƓyҌ;ό'O+3Cf(6Mx>nx|T3.ϊ M3O'ۏ[++%<@C|ydK[(g.y veS7(<\ɞsdA9z|  z#NtmQ3ME鷏[ȉŘ6s s.pp6U&;+N'_< ٳFQ'FF%oϛmy?E{~Dy#L~_Al| dowm6'6yܝoиz_R)!}`?OFΗl*OuHvn˵&wlN)Sol6< w'CmE6C6Eg6՛o˩*/[tl 񾤋YE1hMӸJJPS<»iٚ@JҬL6lg/O?Dg4C hIhw?jcˆG/`x~&Y.ō;/iQ~qK*3U"{!3("qfA;p<$؂՞?1(ꠑSe*E7PqZQ9y&ZJdZQf51*2Q1 jȎ*QjLȌbQdm_ݪ̏6Sʼz{[@q$Yőm"jz,e3C-3Abfqʄ-xXͤ<}2IYW̬&&V;U8YBĘvaܸiXeZV0}ZRwc.u*|t_xUcT-[[zK'WU+V㗵ߑ /_"!6sscU/L^F0{Gz:Jz˦~pm3O<ܗr]ͨ`©NW{w47\ K|םw% 0o,X# EJ֓Bk$B"$B"@llj././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/idea-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/idea-fake.tar.0000664000000000000000000000012313013560574030151 0ustar b63969a7ddd5ae56ec27b3cbc95fdda3a8a8f66fcf13130cd93639e37e42b0b1 idea-fake.tar.gz ././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/idea-ultimate-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/idea/idea-ultimate-0000664000000000000000000000013413013560574030303 0ustar df9ed78b02052a54a14dbbfc65222b3bf5bfac1aa283a72e77f671ecc90f81f0 idea-ultimate-fake.tar.gz ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/0000775000000000000000000000000013013560574026200 5ustar ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-fake0000664000000000000000000003364413013560574030504 0ustar Tul]y1|lc3333C q)ffffff}zjѨͨ5z'J-Zj{80ظZ8{0Xؘ -l$XXX8#+ + wrlw)ƎvFVNwYǿ`IVsrrK =s?Yl,l@6V0;+)?p)N戈 Zc G[ Հhhd߽̉OMۚrN0vvV? BQ^"-%7ぇ05L Mv&@i3%c!>㗴\q_۝u+s$]p?q'hHhOP=^U11]AlpX`E4it,:rrsZk=(lh TǹO/l+-:UV+Q_3CUxXOX_=W}"QfxWNÓz mwƕft25%Srz-dV9B돠3nk .З)s(6} d"Oq1`_R7%Ut>f(jD/ynPʭ+A#K$M[5A"b ܍y:|22 >P'zcHGӃTgjHZ&Y(5aMcb/T@ ]6P0XR3͕!Rv#$4q]ySZ0=KZUE0fND[^2' ,%w|:RйtP3$߸2\x⬵[@ez㥂ku0 I4}~f?. uXu`g'%9Uĺ@qil)7X>UF{NQ)I&:POޟ,+>3rvB5QB;VA_fPD@XO|8 5AQ]XsR^1"0i){iE q\LN'o J-1vȋ؍c82`P(O[ tHR9JIECg_^=i mbMLҨZXjv(:P zl=U4Ù:.B68ر+^M3]E !Ώ=f>]\Iz+OmUN-Kqz9~8{zurbg$/B$GtJvGй$[\|0DS4aK&G9`{9X:||w|E jL(GgLy^5͡palVw}{dznH= ^vMbl鉗J~G/{d ޛw/5͇HhY.҉K/X%,w :j7%9Ȑ\?~b!o]^e`rܜnz<;%d5M`~*1q_'z|p'9z;g.z5#QtNemx` |xzo1ӹ= Q2.WTC>L|npo|n%a m/wpJc?B|1<ߨtrIqIDF,]Z|EV)sҵ 8h|sTg|}w- 7(#xs4a#M3=;`t|=_8V>_ Iy+Bw3,V BtõkotHzב"9T*7n.W@T94qD/UO N~~|mwkz=E0 xEȅԙu$̈́{74Ia,RlMb,A?!f4z //ncϳ.3݃c?K;5jޡ"I?wB rWz@_7hGdh6iߘr<|qw.)dG6 Wl]{Kd;UrY<{Idx>$.xIl4ʗÑS͇m\K5`C8H%o'58 =*=_WiK vr\b*n[Q NJkLNI|GU?,Jͅ7ƍ2ņ%BgP>f:p|rBӾH0subwAzN*HLxfuY-dK ~w{B5'uṱ (ҿI6<8|śZR?"dRTho$TF < Uܕ'<*B!AݓPɻ` Ӫ][pFWwB5Qf?Пj/{vK ssԵFCb#Ǝ@bvAtWJ+d|k2K}`܈c=ca~(b04^G`U;QAsZGک/5R '7@\l!JS]S}vQm͗c>W= _Ӊe *'# 2Է͊ɶ(ӻU}=!E*7L6hIUm"3mj `lyQ3lCya@N!s!j* <ްD6fŎ#-i J"D t$m锹=4To#UOX%L*-[$H@B_!H<$43v\*kIjg/ ˫mJ{T I{rD|Xg<(oYрm/'#'Q< f8wo#d I SmNWt.)ucXL>Sa<(?hEv,S&25%-q'i9mi:ZyPFq9x/ED ՏosD1 r'D쟠/el -dE0WbߤhF_#[,/O:ֈ @9CMJ+Rm2)ňLPӶ+62-q);WV8ar ;`-ulɚ1 dXXX_ o9ny\IoFe&윉}$XoڞP )ZxuMtl}8:ȨaPTVƅE=6G >]AVe[z4G A { 3$#"P m)cw)_tFף0pQS/\^3v$E% \^Zyr@?Wh$/c ^:B^`/m!Dfw0]?%r_D/h]~7GkM(dڬeV 6 As[cW#P9k5Y(J!6xUW^oM+C{6GyF1^│㒿PTr#SV}^Vݹ3۫}:˽h.,TE|z}N9}Mo}@/L XwKwݬH\㉾MJ)O`^6?.{h`:ʈ2x_$'? VXT`W{qyR7#ë!G'o;bEQ6'iHeDSo#|ĈN%cC%#/QyOCv"~hokc#.%h*! cƈtT\;Ҭ[VLJ]'ʤ#׎sN#Rү֥lCye͇EnozV2 $߿! -y +כ4abmX#f兜P'c7Y2?HqQF@\rsxTEr ;jbI0oxۛ٬|BdtMkD=)~C8?1- z eJ醃I+Fg?G-JgPrVs( BT>Tpuq*{cG2?Y ^Oܙ"l(пl.lH@kt_ "kOi%QHbP4ر_3tb+j̿CD|azn\0^ Ęzĝz#N,yVH*M!a &M섪Q&_R1ӿ2v0nBOA9f>9 z|zV~XҹA6OOsTTMLp_~8ёdtfְO)n=YGb}Y>(L6 he< Bv\brKc2a-CR˔aQ(6gړ[DIծ̗|#q(-`a}vKHbMo+ݧn׽.!?P[x'_=2pAi魆ܦ1)Tv+܉8-% JcOc6&-c54灾_-ZDmV'a4T }$$e׷,Z L7×J,H9m捧B[E()eB፪,ve؃0)qlK&2FZ/ތZxlp7XٳxϨ^UU_R3H?OQQƫrk S"c~yk3%FX*gވ1@5{rn(O76*?]B؉sC5 |73+Z8K2넏@vWD|0d*d&_}uF4߳MZn̴2^KiJM<_ bIתY.A[6mAB)_!>Zq"xOXFS/(t8 zz3%Eg &N)8T#lPN7jᐨ2h;tҹ C'Hc"dU6{?(uFn3.86Wa6rwG,v0r@2_uU>:$bzd%uN|3 ;`j&>u${Al^ '*( 8u˥e2EN8|PrdGܹJWt#P$R!lfɗA<&rPȶ<$&ΡkJE_>8U7@1}qEz#351W+l,VaNtDd< H E!pfYYFAد2 W&bC6ABPd v!A㧌c 7 F̻JݔձV׼e$!/|AKEti$0tIRt'?ֲINuHPR" eq]Eĉ\[16V)K G$OIiL4hhwY`u~dsy]кF$CA=g<ӂX=SNRwiO 66=&U_OY%axrak2f>C|s ~m&f>FLC#HC_>'S|-Eki^>ldTdi q:_/?$lJ8M0UKG>rRan馢R:>\;a߈āS?$]|) JpK&~@1$~Arbak7"cA {u3SmtޒJIʀaگPn\o~fݮ롳}`58?:Yh7t@9 pE.lDZ ["TsOR-sh8xn߶#ߧw{.}lۛEV2$!0 w_2p ¥tב7l_a O37ɛAr#oY0W9OtOU ^Lto%$rШADh >{V'p8`]8w^xm^PLspJ#7/MD ȱJ$ѝ  ^ܛ @;yE3wqaF#唝)$5=SVmWR׋jy$OX'D["LsN:4pU':!{#oKnàr`-eyׇK:x Peaj)ZxRT8D #4(4oHq|&]3.8rxHY$PR ]Wc Sk]=k:R1)9>CO9# ]+, r)!:cQty/Ely3w[ h^$w/aϣF0^h9vaq?Xʲ\> p֔fgVM&ReuEՑXر_S&n7O-xj'q|Un#W^&5V7inhteZ4,NdP![c#YU,& 'ל dZn WZy\R8o]9LOÝŨYJPc^SP9^gMr9y١qk2`ڥ@]bdǼ=,PKZxLtsx-cЊT^fw3#N-tBK@$U/D^~v}߬;-D%ŕ⢺n}dL18߭%6A*p&?_/(%m |wWr>o aMxО]6 a䛉:dm!zP؟xOƤLӃ0VޓJ*ܢkw|0\P4գ$ж[E,)yPt$<4i]PPz4I+ h¸YX3g9i3"orBx7Y̯©,J\TW(z:E$z@|",=*I؀b֙IJʐZwt1`>P 4;"]͏hi y/ bNiTeM~>* ?GV!+K-BGUmk8 "{& ALWї"L Z?XHh4MNG_(Rv)U7jdYg0'N!n5hmx-Ze; #("iGE U(Q+3$?[ʭƪFXrF/02$lzux7 RvBh>Icz=FD*2Nu"鑸…klҜxLjӍ0c(DBbUͦŸwyx*t 5RFbd5!GYQȩV q&1!{Ʌn#?Dl}2#eʥQsvǜyxK|7:vn{eQ$;G'k¿:$^s FR5oYzM|<|`U䩽ТH} ꃅ%PdVCV8#i:`S9uk8,o7r+Xh{uѯ_A,͑Mv2Wa@l ҭm$'C*YN=R]!} /$G&tҚa3 <{YHwSr"@YI|~·:CzO=c 0%12t" u먼+8\M.~ց() C\ۂO E.n1dY2M(Q0Zl@cc&762%̀ZHm0r4pe2.gsS|ʝ|Tg"uu'+uJhXR`+!4lR_k)Ebk0ۅ uRSaxSss}7r x/jř!銳<1UUOI@7%0ɢ2,Ph5MY-[>`n,+`4{>ȟ1۫gZ nGtF{#>¥#DXqjᥡKYQ .=,\1,jrTT#r$uz@U^zd6֣t JsBqaB}P^2u74Q1V.N0bPw}&!+ URHϏ ?\4ݕSlGݕbގXe_,)jϥV#F=Wg3Mp%͟PZ`]f1!&8Cq#Lܵ&@L+N,qKB]eL:3N: vwQ=]\4{if2p"m|RvjDyTXymPzĖo#H( ʅPrZ)K0op){rTSuTvajsy},խoQFw{ԥn`hי9#9U<'\tEYy_p]==b a@U.fflEYFNDtu)rlwN+@ 3X*.fCuc@aMYGPvAqfǣVe )g/rC}RF-ծT.]0IhE\Z~^! VG IbQyWþg!k` TS& C nѦL! %ddgWCAa_S\J"xIR8P5,/iV$&g;Mi]Oo^/;Ldv^QTFS1=zxUQHkJx 3<ێN<xJ,% ;f$b0gj2NT9CKI+3.{GŸ+Ic釧7wAџ4Xh]dfUmGta]nyuI!a;s&A?g++vH'4wj*xTRYŒ>]7w$0ƭ9<E!aeRRTdF~&vؖj7*CI)w*H38P-!ϋVAJwyD0[o,TVsn.*K#o&זVPE6cj7;ӑ}AXZT۬f\t_Û|Xmek,  AW>ӺYKc`ɉ/-_%o:}UcP/.g{k՘ӥr4:LUiɬōRT t V"Ȅ2 eʕ,r'`˅d`w{_rgcpK*7}F Z+:tW?WͩFU WDAOǜیO\?v/JJLL ? 4c-q GcqWi-k)ek,qwf Tၖ Ё[Ygx ]*S8$CƢ"HwF]􄬈=SZ[)e@H K5j* ͊,d9{N-h {Qr SR>P9M 2%\fj?"Pb50տĈ 9L_6L(;냁7N-W~+ػ ԛ&#@uw:H~ce`^!f超ܑ獒<_hdr0bС0"gk_1 >J➚Ћ8f( `O̱R"_~_#awg_C2lJԕ:;q/[I70PatN5,JZ,G7gIbt ̵-?AV_,o6E8U>벿_E:,Ըa핤b}_I*"JQG#S]UF],sNP/UFƣe҆a?OX?VC;d7ʑ̉vdT~)O2TIOw-o3]6$[[OxzMUv%x,dRPЇJZK]1NܼP\b/@;mX@?`9k@qupU'&#ӋWwe^E0HqY`cGoиu?4+͋ +T%8pwn_~f{cDɠwzZ/FPȂd6U)+J)H0I 6ᅴCqӣ/?'#J6ol\ 6?74A:O樭z?+0\v#B>u=^mk4ӳ DFajK}ՌKbݙsQx zy0iqy > ڿo??fY99`V?\?+_N&&@Nſ/)LJ././@LongLink0000644000000000000000000000020000000000000011573 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-professional-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-prof0000664000000000000000000000014313013560574030530 0ustar e875a98c6199a6748019b838af6f5e696521c0b04715620fdcd11c83c80e0217 pycharm-professional-fake.tar.gz ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-fake.tar.gz.sha256ubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-fake0000664000000000000000000000012613013560574030471 0ustar f1da47377d7b8db8d31d1ca93bd329853c74738e7947e00297ad1e28d3a2ee1b pycharm-fake.tar.gz ././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-educational-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-educ0000664000000000000000000003406613013560574030515 0ustar ZTupMbY--B -bfff, mLnv&6vg.wbODwVTUtVuvo1aa+@V60';+ da39 k898Yɿ??}?[7S={+F#C'FV&&Vf}3kfs=g=Fc= ğ '`VV0+O!V?ߛ*+FF@N5?uK/P'8/?p,l,ll?09 TdrUJRT罋_o!tdcgo27JY) ?D]2Hz*]n,IN߄}I*>B"#$ e#@*N2bVVВӔX.OuccmbB>uzfX4hBXo>Fwm:ܣ!M^#=yjϜNҺCG<5KG䞧3k+ zUͲKDo'\kk S~6]Թt"cE>_IܢtlWlTŗ %P2߱FBa9^ohVg'c J*VZsN#hI{$WPœY S 7o$+-^OӳЛ$/_B|V9^SIߐ5,L [8l OيcM k,O8dm"(Hٱ>|vw3m0qF}kmQ'OUnB`SADᘙ P\YT0)2kT6>K53&ٶjrgAA/шh\aRw>x~Ougt52_p6{-"l޽ixtF mwg4x1"AGKS.No"br{p+<:+ζ~'a[ ~;iw;SGIl;W۱m+`O:7-+?Yfyo 3qc+hGRᆞ\ar+b*c,Lpr( wa}zącпoF_ wKd멶pϻ$ E2Sh9?:=tk!λ%#iJsi[I`Si{˯V<6>504$%o1i@TTZ~ޖN~- b -" !jyǑ[:[đ2gû/xGG1k ŠPI$ Qp`W$sb%3}  TX =笽WX1.aF$9p)|.g׺B>0u*dSdiwlSzxs{iK J>EC>94ۆ^g/ils橪qݼhT<,@:v;q!sUiQ 4!w"b}$U\Mݳ4\Uw ;g\nf4(:x oܟ{}j%ORvyܛ}2c]0Y~cyPt} x [] Cw跉֍毡gU?%C`!rцR}嵤t-P ")whz;u{b 1s :]^CFW~RKRD~3=Bkt.OLoP֢ີ 7.+윉 t1Piot?46D"oZ3 /dv294CGE52'|[-G2hWFZ 丁^|;l\ch ~\`0`pv^X4\"@ʠ9]o -hvѫь%#.)%%o{`"ˬx`6BU2YЬCVrB ?Ω!é.7~rjb,mO֑=mɍ{]B5O^[JLO+yf{87)X݈xaxߟ av]S!Av;?/!P$*C5x(e6 ½x?>`oy~=zWXl-[lF8-_uE34X0gױf,Ygr34> n>1:N%E:]4x ltJ +!EVJҴA%W<0M< Q3eqZi :y{h8{/W}7 żB,å.'V5%)"Eu5^f,C<˭s2Ck.K{NE2؅ً,n]L\2loHg< $laP24Jdmgr-7셪T<>ϔ⃖ F MĘMdϋoq4rD19[!Y Qte6ͨ#U?w$v#ʁux }~ `KB` S1I+ Sfc D@=<:{iB&:89#;s%b|Hb"}%d?nk mP2-h@">EۥŅDU)J'g`-- SK=ԯ@57o$ ~p)9dq{{5}e e.7񽷜D%nQL6-BiY]H]H3*E?,̄SWfIZ0'S_/H `/I-wdzLv6i*Zy,;WdR2ގ8bsUzrj3 >:`rlx{w-V{9ǔn"G{Y/oɏ0Y%J"&I?$ؖW6Q`IpȒ)'bR6+=j9\8`J= ^ލF d _;$n|NIr#@C z9?[!A[YH&ƄuVRqB&Ȣzɴ<. =ӕϡD$V+ q3w^`:V$˘ x^ME!$7+yԚ' wRgp$ ,8n:NC&-l`~:%A-*|*+ئy9[@g|Yr.B/GQv #7D{[ZbG( 8<8T"r},e.1Y- ^qCq1d|ѴnҬ&Y|spdiyFH֔`7+ |);i;$' s4!=?ϟwђu1O9.'V`BE&AQ*Qq*ak2+HZ{S߸JƵV; #" gש?q: Iv(4nxcļh&{iJHNk.Rˠ?TE]!ciS>\9侅3%UcBGD!=>h|Xj{$@kCx&"E{svҒ$TXCGI )Veg<5z.WbfZ!dcyb˛`l,1٪`(O|qc }x'a5c =BLF"f%IU$pKhn7~6(w;F1pjWeʭ>:Hv[Q.^en]+6@}o ,z|(X}y~vr=Ȱ| 0u?xN+-8Fpܿ!~*m0)C@__C16}]Jns#~.f7̏q[ ؑKM}+-iK}yG=ew U!CTϚG0Mr|NXYvF&J& 2cF̪MמRC.GRGMrT`XT|I~^֌e]<OSd{Z J/yn3N [)˽O"^}Ns&JŽ]X JXqiDa072؄u~}na8ewK&sVg, ɊS- oFj-OBaNfrF.sOk63(B7H{t+Ƿs=7m|H( :Y ,IJKjMo)؅T ш}Im3!ڬe*Fy+.Py(2]07knkd͓4RHs9֬yOX:eg |bH|7od%0s2&[;Iǭc_=՛hk5$$(=ѴPD/LSS;PFEMxvygKi;yBh$RU#3Q&q411j\raF\LK0P`D4aGMA6R 0 p ذj1 4M 5<g˄t=8t?dH?R<Fq ݓ)Q68{%eJe8W^i3*f"sV=Z>6V;s?,_xo &O"֌m%.?;yBVM9FrULoFcΰ6FkKގG}xDNIF!q&1&3Ҭ'fӒ)=o%2zm/NZƷY5J2:.NIL67qDiA>m!q@FUE @%-*<0qbzpb^ u` ҇bϪf.x0X8Bܜ~,5'Fgtԯ22/y!?K8wn;H螙H[ eפq*]0BnG(vRUF[\t ~j<\xV 4c#SH»$ۮf;=@ j?H ?ҧ- ?^.gϷJZ{ެR߿sПO7oN2w~1y/P-ؿy"O7Y6]eɫwUgp+3ә~HhzRI0ﳳ<1b=cciP ЗQw,;'*ims5;2fq|,qP>ưQw~x^[4c9҅{\b49foŁ#KH75nH8-/UW$|d#S |V+J.?x]]*Lއ!_$wm?%j* KrVJy&'XXø2p$l}Bplfc;,cNky=]ex֜BQ j~`.<߯>&ΫӀ]Ĝ@UZ٩{$Wt@Y e! PY|ۡ;|ry©ǮjB IC>HDy._cyJ7;N=w:B>.FMy-8{CP9m-E !|Lff,r(DxlIvDRͲC*rÞw7ZA=8r `R*iS%Hg8!gMTn9f穰-5q`)ˮ>([_[IBUڧ`Iewb)h+R׍m"S[U \F93&xmrS؄} w%ƻXᚙg2T}An[nF|!NSu`lΥA&hcDmh5W$0"Wʨ~5:u2Ùn_n06hl\ X6I0O734Qf$ncrB](']4װ>sDr>P *& U<*~p=]?jo6 y RoHB{TvZMa )v;>EIo6 .!c|\lR~U.Ķֽ# $r5Z Zx?,{1!Yd#x"?Ҫr/JM7/n+掇r8zLYһ82CS /%$٢d'%˭1d/4K[YSRgN0h#2%ĮD{>ՆRJ:0/iVLYb+uZ(P xʳ˵ރpˋ}l#bo4vdЧC;r2[BhG6j8 KU!mX~ͷ8Uh>hy+I8ļ*H?vB%# ju xUv;1||YbxLHD햹.eb)O,dw*4 Tλ(SDT:g٪wdX#HMcx V_#~}4},JDFί)E;,(BhKL鑉VV&p`@yT 8Rj2R1B5x&e{ym15P> ,1ò0n0W}/!P#\z&߻ff-ʼn.:Yy 7J,.kZaKh,W۾|.B7=PԄy(XVTKЁc_sP d7QHևU?CL)~Q쿟C8G"25uYT׉調BPFmh/_G@$Sv9e&vGߩ6-<'wPx3 i({pלkR<#n*3͂H >A KẴɜUwkYRe,@{ψTSrp37Ixw?weN_{w^ÚcB ]u3lα-D6~ZS-VM:5^rg!,ù%LLLؠ⍼MwF+dr[Њ5Ҙ,qKSEA$IJa3GEӁGy/:_7ˉߵ K,BT$(DR WrhdbS)&cb1i;∆DLR/3&Q#*0~Efg WP$xp!ҳ'}ٱh*<1YtEڵTX]f`Sԃy|J *i-3۸kM9{ogq\}T6ͥoPZl偬cX`Q+?2w#@(?Y:2X!/qES%dk/o^ek/=vE-}dYU51k!Ï 61_VS_})U@Xh$`ŗ+iFx׻9ZQ5kR G1QyqeX@TbC/YDK'eW?jt峕 熿,{jeCFLd yʲ&kw d[Jqơi֊(kPxh칒0u ;Դ4 ẂA8`F2>QE਩%VL[3=U[<4fcaFs#۸dY}MaY? z@Qʱa! }~[ '"EKNh dz3(-'LG^=f*ӏJѠf^y2_r=[aεc۞N,O>OU7F]-{;)%E)KJ{xku豿r:\UdӪG{eEƮQ ;|qr崐+sJX3ߎV PcpXg[Uį{ns&@:BKQdg1M+ԲU).qQd 5%@ED@HUY ]*H5 6_%\hp-m2;C_ZrN~9#6ƣ%f/ʋU+F<|WZGiSbw:gg޷*!j Fճ "ZWB~cHh ʐ ``}W2|L:Hr0ypd67<7̊(=v7 E9H"g*B6ז/uGF4ww.7i^x8\XmHIyL=I|CꪗВՠ dɧ‚<&Eqͻһ/ְ!}OLFh%W{1@,_>s@(&7QK }Zx䐤G^@;^ؚT0爢LhOMcr<-q#AwAV8-" Dh!˰ziYr΄m[ -],G38>25(GW I#xDRFw\#yoOkN+kЖ4{ӪD7ʄsF%?ry+JdzWQ7bi 4:ґ~BZžW]aw]}1[ias$ P,<ѸZJP`bˊ-,~D\&m8~VeMS˯,e{i2ޤo7VSyET 3M]U'C-P^'G.U0#.3kߒ4!vΕc+D(_R h͛i.k^X53SR;.Juj5Z;?uSj߁a]ʝ=48/!>0SPBmG?KkFxY]H$CZŅbvo\g1=;4\JŪMn\O(蒙tGR@S2"G\w\vo*7 8LObY?!wY҅,([3Ҧ t`Ǥr KOD3f^YXŗ?ZpcNEf4ap6]Uz!貰Ti]x ,ɩJDؘejҀ}f{ '6,Y6 ~˄j<6TCNc@'NDU;qxwJPI:1ڧ(QӢYA{#1S}]0#aq/%<+[Z@$(S)򧝝Ύ"DSefI nD\ k>rce^>rݑ-Diф){ڭ,j :L nџIV_l|ed-Bs ]sLv`[vv_5'%qnNǾMb0BT[OUwcbRi4.e)lO@]yj2BYsBd+v]Q^'댾3q|aN- g$-3Ju(5ѯ)~LAEuDVVA3#[&-O4@pXҶRc*$MMHVXG=NHFTP^bA#\/lv%GjhX UU%b{aIb#7C;\NR5 Icu'= v=[mA"Y]o /A}2k(!&$[7BL=~fg-rzz7+[cjt3P,3Z S)1CUF)\}Ϧq %^{XT4iHg򏪃ʑRѫ#ڵ(Mp$Dʗ8w _kUj3-:kN}[;=} D˄u$h_K da?_L ,Y9Y37?2Qp3t2s4ֳ6Z __-֑DkhfogeMFN6F| dM :Fv@V0;P HM ~ӿf 9ܿ?u?:>_vV_EL././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-professional-fake.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/data.services.jetbrains.com/python/pycharm-prof0000664000000000000000000006101213013560574030532 0ustar  TP߷yzp!48݂ww;g~W}^սojf޷{u^kzW5'^\\\\\TXn7Qq}_06?Cq73=D^Vy98x9kr?_??Y |Y9;ں{qO7/Xy ?Bwb?o^sg o]PiQi3sԼԜ,]\,mͩ5ۮnT.֎y9QQ̬퍿Sq1s+%(8b7w2b`~Er{Z[|O/ѿ_~^U|'{դTn/6cڛ4  7y'=4S{Xv1oҋing t9lbcCzu6Ucpz:DzvXhdpM$: |itM[Q7;{x`9[Oߛg6adEWΈJF63)0:J|1m,GE<3V1dThכIq`r#6%rx} |yMr-?[1{ZqfH"R(W(TdƆ˒e6Dfy]:P4+,VnǶEQ;Aoe8l]G5TFhΆ|E9%/eXA$mrcrS㋸&&$lm7MI"<ՂiպkmE|kzp]yTt˗N="" _ /77T3>&g5hiiȡegG322Q`03,*yX\@\qQNQ U_#iCg‚ 3#uy>:/Js"kk4Et 3-v vĶGYsWr?ޘAˆ&IYլjo 'پbi}. psTɟ;Z0y߇OZ4f? D5]0?ldPoڴ9]ѝ gN"iM]/!e?goSh%'N9ǕiOl7 x>66fH2^A-mD[u Q)'-r犄T=&3;36ֳ?9z| MSkw ZRi(*AAۊV3x. O />dhF[!lE+M# b0ڡ}YWz1*7^՝Ѧf^-c=eؙOOknGEzGݙ}/-pS+>9x3ѦyDsMʏr /6HN]:§pp.6糶i,ʂQr A 4AF;$e(XwqMLc-)(g3,he.` N=Ѵ*[M@oB33+w-^2*&v=0O/NSqv4s@%CzNNJ+^K+R'*6N3!՜mCfZ3HUx(O_g ,MxH-Y7t{yHիrT؃љڼ ڙ Ò bϒHDq`7C.n[(S :)n&N5}2z}8ke{ ͫkozrIpD8\@֚v±T68Gl_m>%XˏQ-eьi _8OLjLXG  ˱j@h"[TL"MMõ~^ǖ1zA+[ tO{Cأ"EGDj: Qhk|7Sk7S\gEh\:@TBAgGСmGl0e*(JrOTvp̤-}=3wo I?]<[_ 4~FQ8:iټEA3X?d5GHv)tZ%.K4D@L"YL MD VtD JPeI$`p ĆXD`5p0Y|bQW۫'|4Yʯd屒,hBI,PcJ}*ɏ/}[#G{()2Fz}@7tNK;q>{ (vFuUR0{篋NȻ>t s01&Hm#f/1=YMoi@M\N0@esPH) ۷xKWn(P Y[B<^r9|5 l 70?wp E~MChf//щn:chC1P7E!v]@l~8=YЂ:|^.}o͢oMb^DoS o_,HS9':}/_pg.^ƛ0u77/>5"sDdah5D[@zi˙wetxNzo‚XG= IF?.`[HaT`LF$zhH GHЌDNn{?E>ַٲA"HC(eqqxP@6Q#H6ֽ|U㽏gn#"C2`9 FVj?T~#ogwD"4.-74oHv c80Rf? q/b|A}9qc#nf56i:,~7?>Z܁81f1x(6J#jC|s=J0Us/0HVj5G$_bUy"҇f>:j8K0s2k8[){[>2;1.:ZHzHR5`>' P$"Iu0W%Y''exq4?KqQy;|aHKjd?S ϸM5E-CLbQrMPb}62^BsI.~m[ic B]I4``2~egW{w^]SL-|7oKx=KhνnSa]0޴a!@ rph+V 3Ik4[v2l[vMK _" (xJ8| ܄۰]1!>L@,߄\ (w+ +15G!,4(wg/a1(!8jcgPނ@39Ђ>"#}nFDy(Md_{bDd7}에}AJ sZuoʾ/j1tg{=ʔ%>XWSyOHs\MəZQڡYL8;G+1'" V-g8yl&TD :#@(u %y= *^2n?a\`uc 1=#f8v);|e(ujKN)7)^ӵJ~5vy3jHPwo;# xڳ[O!?@ߦ_#*sR?['%Jkv(H}ɷ*e$/ur[ӷoP`:VWċ4C<o؊gF=I/D})"=Upubh0BÝ(E8:U7BRV`JP*ћ X h{4B:gJeB 3w<+]Ls빬 gvw_h uks0]] }[̟b/Z W; cL֢ HOQXiRT"C;e8t>;SY(~}D^vY72ItlPƲvӴ}J ԕϫ 1'Zts jw5H#b#[(eMW:e-B6 w7X(QRS4(<`_f?"~ۆyAؿ7\4tʕ-GO2\E%6/ m,[t38Ws(/v0ĝ6?pT(0e~},Ȭzpg7RO rkenWZ+Ъd -%(5M5 @7%@[vnPEvmWSqʩ/5v:;=2BbXzjƦ-֜uk:PO ?b7\϶@RzDB@"@_(`'(6AԅHOӳN|[ןo GLM6j'زVtxV_~[u[s|Uvb+?4d,xɼX?ϓ.7CŢ fj$C(IzcQixLrԍfW,kk.7^b8Q4z`d$R*?>i`H; ^UyH.gI|-y#\|@;nb )J2sPo[SYC _{C@ }KOpˑ@ĵ]ևJr'gݼhݨz7jX5܋d(`ZcGs-l릻։z:MH\* i_q[<HA ̭g>9 ;>)h~Qlt-(=!@B5.!\|Π*Ow"^h]Jz-9"NKǮLZR9}։TϙB5z[dl8z$[U+WES6U }xi꠯=(R~%kzJƺaWs;9%GA&mnH}8󗕧^SbX-in-hՒ>[C +Wӱ}-]󨃥6؏HNSrNtax牯4׏U۽//76&)E.S9뺜2JR);ٌF*f'v dM!U0KVp3K/_8apb]vfwFBj8uN_\>ޘ 6Iɤl% OWz?IfUp-y<^5nSd!Obkĝ~jJu-1]E%!{@) {c-X}_kYkg%q ȃ o'זm7 3xk2/ 仕;" 7cR:NE%RUK88)( j)Al7@M9꼢VlelUo>,!~P5RbWlf *_,͍[׵}30أNfG♌. QU#O6$-qAP $iVFzzc)k5w*֭߄Y;Gdq4_즔68g>툐 YG+ ݀~C%Phgpi0L=L FK`*k3:2 ӱ o+EfH }!'+3h3#[ cuĎ-$(;=ᴾIm`B<`#a@xA0EO{wn0-_\Rh+b`4O)Yb ͝ RE=lG l⁰S?cAR_!7%MHIEǟnvW>h{(?<"Bu-)C1&$ޗ%FX`o-g+.[ ;޸Z@$-i^yKլF(1 @ixu+BȎ.>\@dA_Nq^v9p)uY)%3I;+{XrɂN$ _N~C!n \b|fss |hp̂{e>Upi~+Ӿ>8ceM,==ځS l9{1.ߍm|) 6Y=U4Mœ+j/ 5#Njggb:pi:)(;m[A2J8Ki2O\6,Ot.Ύ-[}&Is^nZpЫ6M2~κ:Z2"d:{ګ|.@ _^>_h!8t.c5 {_LML{MSi1 +.3mSdO$]YcȾF.Ē[ 6VՉu͎:ȞC̗WT&81hUg9It}WIyE f&sA Xa]xiU:j#w4dҫ ISQW8忩ߨX느CC:lS69y/ɷy~b#QؚG 57ݕk5iٻJ`.r[NT<9׶y\Rk!艪?59~PTs=^Ma.XP6aHKoRlꃻ@[&/,!I~d)9v#A)ddnv5uLJ9_S2(zOH^Ylam MY:E*'bSyD掽֏юBܔ.JR{|݉s5ur^݉yrӅ9[8 NNfn]G Bcc1HHCӬғ^O45ɔ"ݭѼ]f;>ԊϕrN^N=\$QVW=_DzZ>JR'H/x~eQeqzvg-]D5qb0h m )cˬ$eQ(i2VqKP"'3&k]P֍P73*fxKe<>sОȂL q ԋ6_D';#x1XD@U;@+d:ˑH86[CĴ.亀slD&/;NʏqŘ5Jaoqʈ")b0wcA"6oLtd1<4i*$2]< e%,W[Aއ [8 OUxN(uHΎp.2i၍Ӱ_j.gZGKFl4f-]P2pO$\9r*AYX=_V2F6!3(!*l'𥳐H86l.XWIe@د|wCP9y.\ P}Eͺ(KtOc+pKnv;Z{]4:9xMWSBrQε,/ŐtL/3m[W* 8Ib|Tg A,9y?DS>۝U2+FbÜ8l,op3 ewvŵNyں߹A*D].HT*U.gV͋;! ɭR^:X!V_wxh^)9z17vבRt9@UX&h4O VB&!g,x!_ݢm?DI\qv%(~;K)ـc! J7ż6$ۊ]j 8^үW!hx ^<( !2kTjlވ 9$QwX0aۨZ@.^V@E=2~p(oh6qX]@p)=UHT&+ icM/ʛO+qpE'訪tB &6k2]^fIi׏Ǚäq*J*MU\F"6 o_l'=),}m؊ 7f㌐jO_kV՛biKdʼދ8Γ"'>32Y=3~z$T_L7xDv-TcNtZU| /-`% 1-yqQҀVI\)|&GJC>RĚ=[0V5hca5cwӢYhF]Jp,XJD ,➱o'pKVˌ񾔦#|"1۾QKjTcω`uB'IMؗƧ6.ʊ)a tąC0%6j3/LXP@ J յj7ݨ*MvߠsdڜTӋk 7pQV6?== >΅e36XD-{6`AauR<Oe>{$d|ً`,fg [Va7#HOx6@2}`+;l-H6/dC6XwW&bLIg2Kϟb~|%$6_yaS0Q y(gM?ZSnKұO%PΫE`F"3aC%9 c8C$}W 9͌.7\+Q$$fa(eA,~/YP/ȭ2}Fcl}=a3&:[lNii֤3>G*!bف5..~HVJb :W]nKmKW4 c(˞I~}oe?ȂTțB._+bTsϫ0Wsd7u_M <YLGz@.$W5XMZa@(F>* %'I)7]>9A>?Pocx|p9w3~F|qM~W !SP6GG1!V @=28ڙƙ)t -ʡōR =|EfA.vx$3y!JLa7[~&? hg 6+28z#üQIyoT]|DWu^x=CBzO(]"FƔa(/h_ ?F!(eKqy= b=!auP.)(]Neߏ nno 4'0mmM̊,=/qKրqFg&ǐָa^T1{.">9FdCq)m;o~=g4b/oJ۱K~ < zҎT6c*nQ$K9*j~|.7R<ƕ( txCGQK  H08Eg;j,(K+Vl"M?]<[Ǻaf20UN&Akt$+8I ˺r~0W#$m֗E…˧ A;r뛿KݳR]s%|X믩HuUĊ3eD4L \X +3OФa}Ԧ/{ F1 /de_@7 cQQƦf;Grfc-hl­HT0z wP'Z}=)15?0en}qv\stk|SF"IB05A?)c& QZªs, 9Kj $@-> Og[HOG0aa^;Yt{XӲϜO$#.FEz1DE DM~\ߓf:V^ThJZ]qcݼH Cgrz9\Ip~6(pUQ"*п#H,~44_HPwJS%dZ z_sG3ַ%٪[b7Vu؍zYy&rv8wSwZjjZ? ]#?ZcaDŽԼd8'V22D xZD~3ch<$P!Q"ǂu2é5 5KJM#)*Z@6!b:B\ >3 |;;}eۄѱD=ʥs,UwY%#) nyU#?ڕ#X[|!er#Lx:=_>n#bmjÐrpQ4h. Ѽ9f9 mH,kV^ '_g$ZR F;ߑFց){o3|_*}Wfk)u߶|{>$O$µ<㣂9Z,'7tۅbn;e52dj.0d/ g H*}I3EF%eKJtJ_8r <#x_ TDrBr֬譣r64QAzۇ'`RnZ^dF xW+ё;+ 43ӵcl.atT*<#0ۆ/\MHBϗ7Ka00̡ nu8:k “@TҞ6afqyNog19GJvn4./y޺`SH) ك^0^߱?r EF]oγW7l c"9'dvw>Y#q3 3f> oB0sL;ywF/f_ +^T-bš],JIJX#tx'D^KrDNdzޭ4kf^Ӟ-pΒ,c3>J,]\Ȁ.몹2*c1TOgBa:f=%6n{]%tݖ; CiA0 !*]1J>ă#~'5T"o'cc dWL*+ scR_##LrE:QO;WqNr;pm~SurʸQb3R#OkVSC3XW7h.fp?HЧm[ e7cEPل 2ڟhw"^%S̘PCNGT 5:8ߚr(-A?@(LtDzF~B#Bv].5^GoNn09,u Q!_;F%.`?w6uk3[]Hs^Yׂl??l:㉌9 VZPmU!i}lHğ!s\i){7Tfjb._ģs@{Sn/(;:$<1ЎALFu,fO1 6jp;|= W}"RNDξOP'͗I I)6͜,^ <ӣuE\~[xZ,_qSE.S$EA]HKl)RrէxT]ۼ:S)a1^.CP .L9B F$#19B~Qf$qT̨-v;N4@8)dY$a^|u}21f~\SZ>'LՑ-wIhJxjڼh?$ ~I~u=sQbGI'9vr8J&Nokw6u_M?ht6r+L;Pd'2̙1Yi d ߌdDTr? Ѹ!,NYzȟzNaQ{mdk!pV#N!8 By%EF!MOVsM;3'?B(=}_}/$6hH]sNt nt0`]a1gщl5Х (ߠ|'Lb&cia bP+ 8Y'㓿ƔR*1c nodcM\鲋'_/Aĸ20[Tj9 ,Ѓ7(+PQAe^h{v8H8MU'/_zL!{(~uztK5N#Gُ$w)s٣Q Fm1"݉$A~$TZ0iBL6b!5"ec8 h<ˤ4kF9wnh1G/ZTRPM?D0%{LFxK͒L; .z7n?bJ:3.iDNG^8 7_& ؈A+~uђ=R!=XBݞ\DQz^\ Wٲ:u,a ȦOWXpT* 4ޚ_Uߣ9.__IJ|}ACS!:,'G*" RPuS^w0nD  D$@~أ!&a,pw1;h{" I`+ZttIL{4 iS^H,C~/0#hY3={~>yw>)T# f\*h` 'Evdd7bv0_23Z8b!!ͦx>lrx ak{=Źj_P]یm(nCYvh"=ׂ~C|^X!ӝJ e#Dbh#*]6 ~%WgH &R֦˥- 6PC4(!#% Hw 0H0PH(twH7H( >dOxw=Gw4LBDys@#AV`F>%Q>lZDMݸ_է.L/c_ ʓGjn7OB"({ Q qcn]`1gkevS16T+M]ީH i?e}Zj6Kz 44:ڄ +QtC+ ${~Y&S'Vۡ9 E=3 ~h@ ^hw,'TKqӯ/8@G+mv:|f᫄O~jZ7wyb4{/ ^OW., H].P{=H3YdㅞsϼFdw}}@'Sʕp6#!3aDhl`|@h κLi߽$-C#ܧ!ri[cDz=Kŧ d**\^TEɐS=QR;cJOK@ xSF<Uը-paV|+yσ4wK-We<.gY$fԎ@#l)⧞bW?n? qs[lè.2pb@1y=ޘ.ll4%^{%[r>t.:?SiDzwhtIӃ/ [W%q*+|樜HSseN*GktVGwqps P*t6XaH]N^t{ժ! ;ǬoDP01<45#VzS8D T q] 2{,&؜A^l`^= bۺgByNH  $F EJZ"14qd)pO@V+Ʊe(u*TMEI\p/$50)^#[%eQ="9!Ё֙H4U?+sL!=|!':]gR {9 S ͉aIZ,T/?aZl,C˂$O\IlQ9ƟuJUHh%*W )Z{UIB:ʭxzscb-|)Vo&2S2uIb(iղ|9.Vw8کYRݹ:th?+mpІ:pvM~c@,{|zB[gCl[i6~E =-5Vl1Q6|1مl1 伅BN!w<8#tB1h,CZwcf0<> ܗ\e)2:").!i9 7rol˾F\&^nhS Όl R.Jڮ %fL֡l%uG]9KdM}H6նc_nhߠ|q7)"|\2xSvfڞj=YM 0 j ّcP3^r^%>rB8o^"08)#6EW',Um;+ f"hwY;|]x|zIuP_T7c8Ձ|ȩ}vN'|W1WvlhH9/#xʼU3T#4QP#C%J¿sY<h_MumetԠYdr㈘̌>̏~훾^]]T O*x*ִc N8ڏ ό}N,7zKP6ݙʑF5TKIҽ[/$[OR4^SJE^:{\o`F7r&>', ,wŅ9d44vDtA)? -Z"=\GeuEK[yE2x~c:B,Ėzŀ"a|Z;Z0hoF#~unTBlAgxǶN`Ц UwFw?pĮjJPF `u\W݋#޳,)a EPn=hjٓOڕEwPR{:u-)\ѧX|>~zkGtЫ-A濈v։,՗h:j@%/$hp;F@9"0SDbG]84XqTYFO,Z&.")i*\jzy\Z:r6YD [sM妦,9vN\ 3* -!~DQhsYG,p;}!:x*>dC쒙Jױ3]f.f9· jbx*GchVH pOU-Ը]O*бn Yҕv-F[,@ ;&p7Tjն&:=Zk$?J0|r0ޛh96nr7޾>KȊmNLϵ+1zBNy,|8J/771|+DTzQM&% 2h3с - qÝ/CNoo7/gg!GMg N MܻZ78Y׻>xl@ۢx&m^nfBrolLoUEk{͆NodX$ۆYv7)ϻ#K$mrlK2O}w?2Ǥ{? ĸb LyK(MmA),6nWb䚾3f3Q4:20aD2[,jLMMfbҦ;$e32aLXV{*NSdA]LD\t(J c(|TpVzY>?9g*r#ev[d5p{\sǾ$5!&M;%1(ͷu2TSr*L;ϊhRW=^XJ׻ŃJn|NݙpT Xb}qg4(vt9^eDQM3쇰 Y%} oTU,dp0hUb #n;< 6^ضoj&y OaYܮE"sORfĪ|?}>ggfV̯z2)@,/󪝭}5#:Dw ^3$, t5t6@ּuˌ92÷el#48R]PKQ8yyzuiF s7r$hW #p }$bӜl^mοlԕ)Ji$f8j7[_UPzxڽi1VxE~ick/E.+ٰdW0-.,x"hA1oBIIsalQX񑓷|Bl!)cF(T+|yuWz =ǧg`]C[bz{7G (O 受dbs4+ϘʚDOM%'3 Kn s plf1agH|,78Í^2nt{LdK_0do7~U:76H ^Mh$P+'Ahʇ[ۈ0ֵk}uqjǃ2ǵ NV*WifD0jaad/mHԯ`;jD%sN\0VIWs٩&}gauAC`T<_>%YEEөc՗5m/"|F\\ j^?<_ϓ]-j7NNIDjhH 6 ._݈Y%z`ݺo/) bNgq4DCɿLh# хiڕΕt h,L] T\DԘ}t/=a-/#-)œ˾kg>i%*ѻ4YA0ErA6֯Gn52\bPh9׿ QsMOCrD޼Ķ7XQϕ\0^}n92Õs ^4JšnI8*" BD]"t@_id2fqo>B kttuwy˳8IɎO"5wqSnJ7&G!VfrX{4$n%~iyv\DN? ^j|(RѕRuiQ؁xNՅ%Pp: _sHץ$r@(stJD'M; b c(S:T!WY֕$?b ȗz>k_b EL~|lPP[*9kl.o\1zo0s[^CMK\, 26x\uJ=8:д {~DdTiY:&Gl .{ܦD{ j5FE4lw3H e蓼+Qu23ԕpREgL)ώ3BG&X$au!e3?_XJ,/s0ӘACNW*UQI]"U)A4K"OWnTaa |/@6LD_h!Ǵ Y9PhĨ?^V,[VY m|0ԯئ9!%JuPG^aaz7U>%j8ؕgaBETot`opj۱kaEC8+Fm tB!$`fXD$9]lB#X)^y)6$u,#JV;(vQuN&o޻Z-ZRh[>'w e ֛+]Xʳ…5J&A^v^}bPQmREbf\j@^:Hk@Bj,NUZ$f` Tߒ!-`,P-3 k`H_0mEN5=w&l.i6܉ğ3Å;+sKvGDej.fd9O0rr{rj<q>XqImJjKA^.pjYq-u,UEOvF)xFm5ymfJ-,϶Gmjx66`? ` ܖg׶xs9zo,{l2jHGIfǗ`Wk O~+F "* + @k?qj$IlVfH WfS3wIuO ӗĽgIfb\ iX1Z?_ *BZs>8pnE`>G|ZjZaU a Download Android Studio and SDK Tools | Android Developers

Android Studio
The Official IDE for Android

Android Studio provides the fastest tools for building apps on every type of Android device.

World-class code editing, debugging, performance tooling, a flexible build system, and an instant build/deploy system all allow you to focus on building unique and high quality apps.

Download Android Studio 2.0

Read the docs See the release notes

Download Android Studio

Before downloading, you must agree to the following terms and conditions.

Terms and Conditions

This is the Android Software Development Kit License Agreement

1. Introduction

1.1 The Android Software Development Kit (referred to in the License Agreement as the "SDK" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK. 1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time. 1.3 A "compatible implementation" means any Android device that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS). 1.4 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.

2. Accepting this License Agreement

2.1 In order to use the SDK, you must first agree to the License Agreement. You may not use the SDK if you do not accept the License Agreement. 2.2 By clicking to accept, you hereby agree to the terms of the License Agreement. 2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries, including the country in which you are resident or from which you use the SDK. 2.4 If you are agreeing to be bound by the License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the SDK on behalf of your employer or other entity.

3. SDK License from Google

3.1 Subject to the terms of the License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the SDK solely to develop applications for compatible implementations of Android. 3.2 You may not use this SDK to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this SDK is not used for that purpose. 3.3 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you. 3.4 You may not use the SDK for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK; or (b) load any part of the SDK onto a mobile handset or any other hardware device except a personal computer, combine any part of the SDK with other software, or distribute any software or device incorporating a part of the SDK. 3.5 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. 3.6 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you. 3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features. 3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.

4. Use of the SDK by You

4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications. 4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) the License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries). 4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so. 4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier. 4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so. 4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.

5. Your Developer Credentials

5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.

6. Privacy and Information

6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected. 6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.

7. Third Party Applications

7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources. 7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners. 7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, the License Agreement does not affect your legal relationship with these third parties.

8. Using Android APIs

8.1 Google Data APIs 8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service. 8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.

9. Terminating this License Agreement

9.1 The License Agreement will continue to apply until terminated by either you or Google as set out below. 9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials. 9.3 Google may at any time, terminate the License Agreement with you if: (A) you have breached any provision of the License Agreement; or (B) Google is required to do so by law; or (C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or (D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable. 9.4 When the License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst the License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.

10. DISCLAIMER OF WARRANTIES

10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE. 10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. 10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.

11. LIMITATION OF LIABILITY

11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.

12. Indemnification

12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with the License Agreement.

13. Changes to the License Agreement

13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.

14. General Legal Terms

14.1 The License Agreement constitutes the whole legal agreement between you and Google and governs your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the SDK. 14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google. 14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable. 14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement. 14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE. 14.6 The rights granted in the License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under the License Agreement without the prior written approval of the other party. 14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction. November 20, 2015

Instant Run

Push code and resource changes to your app running on a device or emulator and see the changes instantly come to life.

Instant Run dramatically speeds up your edit, build, and run cycles, keeping you "in the flow."

Learn more

Intelligent code editor

Write better code, work faster, and be more productive with an intelligent code editor that helps you each step of the way.

Android Studio is built on IntelliJ and is capable of advanced code completion, refactoring, and code analysis.

Fast and feature-rich emulator

Install and run your apps faster than with a physical device and test your app on virtually any Android device configuration: Android phones, Android tablets, Android Wear, and Android TV devices.

The new Android Emulator 2.0 is faster than ever and allows you to dynamically resize the emulator and access a suite of sensor controls.

Learn more

Robust and flexible build system

Easily configure your project to include code libraries and generate multiple build variants from a single project.

With Gradle, Android Studio offers high-performance build automation, robust dependency management, and customizable build configurations.

Learn more

Develop for all Android devices

Target multiple form factors with a single project to easily share code among your different versions of your app.

Android Studio provides a unified environment to develop apps for Android phones, tablets, Android Wear, Android TV, and Android Auto.

Learn more

Code templates and GitHub integration

Start projects with code templates for patterns such as navigation drawer and view pagers, or import Google code samples from GitHub.

Android Studio's project wizards make it easier than ever to add code in a new project.

Latest News

Resources

Videos

System Requirements

Windows

  • Microsoft® Windows® 7/8/10 (32 or 64-bit)
  • 2 GB RAM minimum, 8 GB RAM recommended
  • 2 GB of available disk space minimum,
    4 GB Recommended (500 MB for IDE + 1.5 GB for Android SDK and emulator system image)
  • 1280 x 800 minimum screen resolution
  • Java Development Kit (JDK) 8
  • Optional for accelerated emulator: Intel® processor with support for Intel® VT-x, Intel® EM64T (Intel® 64), and Execute Disable (XD) Bit functionality

Mac

  • Mac® OS X® 10.8.5 or higher, up to 10.11.4 (El Capitan)
  • 2 GB RAM minimum, 8 GB RAM recommended
  • 2 GB of available disk space minimum,
    4 GB Recommended (500 MB for IDE + 1.5 GB for Android SDK and emulator system image)
  • 1280 x 800 minimum screen resolution
  • Java Development Kit (JDK) 6

Linux

  • GNOME or KDE desktop

    Tested on Ubuntu® 12.04, Precise Pangolin (64-bit distribution capable of running 32-bit applications)

  • GNU C Library (glibc) 2.11 or later
  • 2 GB RAM minimum, 8 GB RAM recommended
  • 2 GB of available disk space minimum,
    4 GB Recommended (500 MB for IDE + 1.5 GB for Android SDK and emulator system image)
  • 1280 x 800 minimum screen resolution
  • Java Development Kit (JDK) 8

Start using Android Studio today

Android Studio includes all the tools you need to build apps for Android.

  • Version: 2.0.0.20
  • Release date: April 7, 2016

Select a different platform

Platform Android Studio package Size SHA-1 checksum
Windows android-studio-bundle-143.2739321-windows.exe
Includes Android SDK (recommended)
1166 MB
(1223633080 bytes)
c556debf40de6b5d6f6d65d169a64398e3380183
android-studio-ide-143.2739321-windows.exe
No Android SDK
264 MB
(277789224 bytes)
3e8c25bd7b7f3aa326f7b2a349c4d67c550d13ac
android-studio-ide-143.2739321-windows.zip
No Android SDK, no installer
280 MB
(294612422 bytes)
705c00f52b715d6a845c97979ced6f9b1b3f11c6
Mac OS X android-studio-ide-143.2739321-mac.dmg 279 MB
(292574501 bytes)
0f3d53a08815c00912c13738abc79e82207b20ed
Linux android-studio-ide-fake-linux.zip 278 MB
(292106971 bytes)
f2d242b292b63ce103209b81d2ff0f4baca7b797

Get just the command line tools

If you do not need Android Studio, you can download the basic Android command line tools below.

Platform SDK tools package Size SHA-1 checksum
Windows installer_r24.4.1-windows.exe
144 MB
(151659917 bytes)
f9b59d72413649d31e633207e31f456443e7ea0b
android-sdk_r24.4.1-windows.zip
No installer
190 MB
(199701062 bytes)
66b6a6433053c152b22bf8cab19c0f3fef4eba49
Mac OS X android-sdk_r24.4.1-macosx.zip 98 MB
(102781947 bytes)
85a9cccb0b1f9e6f1f616335c5f07107553840cd
Linux android-sdk_fake-linux.tgz 311 MB
(326412652 bytes)
bc1ccd6b05beb06f59a2011c5a7f2bbab8e87f02

Also see the SDK tools release notes.

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/developer.android.com/ndk/0000775000000000000000000000000013013560574024324 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/developer.android.com/ndk/downloads/0000775000000000000000000000000013013560574026316 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/developer.android.com/ndk/downloads/index.html0000664000000000000000000012601313013560574030316 0ustar NDK Downloads | Android Developers
Show navigation Hide navigation

NDK Downloads

Platform Package Size (Bytes) SHA1 Checksum
Windows 32-bit android-ndk-r11b-windows-x86.zip 728894948 b42da395440cc1c5dc4eeeb383679331addeb3ea
Windows 64-bit android-ndk-r11b-windows-x86_64.zip 771396549 480eca1b29cfe73a5b35374730e6a82ca65c2aa6
Mac OS X 64-bit android-ndk-r11b-darwin-x86_64.zip 772411311 c64fb355fec4da57d329ab45bf0aa29a1aec58dc
Linux 64-bit (x86) android-ndk-fake-linux-x86_64.zip 794138413 f3ba966ba157abc7dd2f21778afda0e4a049dcbf

Select, from the table above, the NDK package for your development platform. For information about the changes in the newest version of the NDK, see Release Notes. For information about earlier revisions, see NDK Revision History.

Release Notes

Android NDK, Revision 11b (March 2016)

NDK
  • Important announcements
    • We’ve moved our bug tracker to GitHub.
  • Changes
    • ndk-gdb.py is fixed. It had regressed entirely in r11.
    • ndk-gdb for Mac is fixed.
    • Added more top-level shortcuts for command line tools:
      • ndk-depends.
      • ndk-gdb.
      • ndk-stack.
      • ndk-which. This command had been entirely absent from previous releases.
    • Fixed standalone toolchains for libc++, which had been missing __cxxabi_config.h.
    • Fixed help documentation for --toolchain in make-standalone-toolchain.sh.
Clang
  • Errata
    • Contrary to what we reported in the r11 Release Notes, __thread does not work. This is because the version of Clang we ship is missing a bug fix for emulated TLS support.
ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/0000775000000000000000000000000013013560574022016 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/android/0000775000000000000000000000000013013560574023436 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/android/repository/0000775000000000000000000000000013013560574025655 5ustar ././@LongLink0000644000000000000000000000017000000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/android/repository/android-ndk-fake-linux-x86_64.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/android/repository/android-ndk-fa0000664000000000000000000000067413013560574030365 0ustar PK]pHandroid-ndk-r10d-linux/PK ]pH android-ndk-r10d-linux/ndk-build#!/bin/sh PK ]pH android-ndk-r10d-linux/ndk-which#!/bin/sh PK?]pHAandroid-ndk-r10d-linux/PK? ]pH 5android-ndk-r10d-linux/ndk-buildPK? ]pH }android-ndk-r10d-linux/ndk-whichPK././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/android/android-sdk_fake-linux.tgzubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/android/android-sdk_fake-linux.tg0000664000000000000000000000037213013560574030316 0ustar 9Uandroid-sdk_r24.0.1-linuz.tar 0]FqϣMP2gP$PKk6 UYHxGcJ4^_TZFXlbQzץmsgܹ_*5M+=F' s[{uX_wy8'ycuޓrǺ[@~ғ(ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/0000775000000000000000000000000013013560574022415 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/android/0000775000000000000000000000000013013560574024035 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/android/studio/0000775000000000000000000000000013013560574025344 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/android/studio/ide-zips/0000775000000000000000000000000013013560574027070 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/android/studio/ide-zips/fake/0000775000000000000000000000000013013560574027776 5ustar ././@LongLink0000644000000000000000000000020500000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/android/studio/ide-zips/fake/android-studio-ide-fake-linux.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/dl.google.com/dl/android/studio/ide-zips/fake/a0000664000000000000000000000256113013560574030145 0ustar PK%XDandroid-studio/PK*Dandroid-studio/bin/PK F$android-studio/bin/java-fake#!/bin/sh sleep 60 PK Fandroid-studio/bin/studio.pngPK tF y--android-studio/bin/studio.sh#!/bin/sh $(dirname $0)/java-fake exit 143 PKJ7Eandroid-studio/sdk/PKJ7E"android-studio/sdk/platform-tools/PK J7E %android-studio/sdk/platform-tools/adb#!/bin/sh PK J7Eandroid-studio/sdk/tools/PK  J7E android-studio/sdk/tools/ddms#!/bin/sh PK?%XDAandroid-studio/PK?*DA-android-studio/bin/PK? F$ ^android-studio/bin/java-fakePK? F android-studio/bin/studio.pngPK? tF y-- android-studio/bin/studio.shPK?J7EANandroid-studio/sdk/PK?J7E"Aandroid-studio/sdk/platform-tools/PK? J7E % android-studio/sdk/platform-tools/adbPK? J7EA android-studio/sdk/tools/PK?  J7E  Candroid-studio/sdk/tools/ddmsPK ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.unity3d.com/0000775000000000000000000000000013013560574023351 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.unity3d.com/download_unity/0000775000000000000000000000000013013560574026410 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.unity3d.com/download_unity/linux/0000775000000000000000000000000013013560574027547 5ustar ././@LongLink0000644000000000000000000000017600000000000011607 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.unity3d.com/download_unity/linux/unity-editor-installer-mock.shubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.unity3d.com/download_unity/linux/unity0000664000000000000000000002413113013560574030643 0ustar i #!/bin/bash echo This is a script doing things... __ARCHIVE_BEGINS_HERE__ unity-editormock/0000775000175000017500000000000012571036405014557 5ustar didrocksdidrocksunity-editormock/unity-editor-icon.png0000664000175000017500000000000012571036405020635 0ustar didrocksdidrocksunity-editormock/Editor/0000775000175000017500000000000012571036350016004 5ustar didrocksdidrocksunity-editormock/Editor/Unity0000775000175000017500000000002712571036350017041 0ustar didrocksdidrocks#!/bin/bash sleep 300 unity-editormock/Editor/chrome-sandbox0000775000175000017500000000000012571036324020632 0ustar didrocksdidrocks ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/0000775000000000000000000000000013013560574022424 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/0000775000000000000000000000000013013560574024577 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/0000775000000000000000000000000013013560574025363 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/0000775000000000000000000000000013013560574027355 5ustar ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/release/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/releas0000775000000000000000000000000013013560574030551 5ustar ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/release/version/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/releas0000775000000000000000000000000013013560574030551 5ustar ././@LongLink0000644000000000000000000000017500000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/release/version/point_release/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/releas0000775000000000000000000000000013013560574030551 5ustar ././@LongLink0000644000000000000000000000024000000000000011577 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/release/version/point_release/eclipse-jee-linux-gtk-x86_64.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/releas0000777000000000000000000000000013013560574037114 2eclipse-java-linux-gtk-x86_64.tar.gzustar ././@LongLink0000644000000000000000000000024100000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/release/version/point_release/eclipse-java-linux-gtk-x86_64.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.eclipse.org/technology/epp/downloads/releas0000664000000000000000000000041413013560574030552 0ustar ЎTJ0\)"]dɉo#,nJ7U 1h '.)Ԣ 9IΪ92QN iK^j^ hc;m+N}c)Ԣ 5rIΪ924Җ<-AJv86wsoT8cJ3\Zk(2cT%)Ԣ 5rIΪ924Җ<-AJv86wsoT8cJ3\Zk(2cT%)Ԣ 5rIΪ924Җ<-AJv86wsoT8cJ3\Zk(2cT% Eclipse Downloads Skip to main content
Eclipse Mars.1 (4.5.1) Release for

Try the Eclipse Installer NEW

The easiest way to install and update your Eclipse Development Environment.

Mac OS X

Windows

Linux

5 Steps to Install Eclipse

For the Mars release, we are introducing a new Eclipse installer. This is a new and more efficient way to install Eclipse. It is a proper installer, so no more zip files, with a self extracting download that will lead you through the installation experience. For those not into installers, we still have the packages and zip files available on our download pages.


1. Download the Eclipse Installer

Eclipse is hosted on many mirrors around the world. Please select the one closest to you and start to download the Installer


2. Start the Eclipse Installer executable

For Windows users, after the Eclipse Installer executable has finished downloading it should be available in your download directory. Start the Eclipse Installer executable. You may get a security warning to run this file. If the Eclipse Foundation is the Publisher, you are good to select Run.

For Mac and Linux users, you will still need to unzip the download to create the Installer. Start the Installer once it is available.

Screenshot of the Eclipse Installer executable.

3. Select the package to install

The new Eclipse Installer shows the packages available to Eclipse users. You can search for the package you want to install or scroll through the list.

Select and click on the package you want to install.

Screenshot of the Eclipse packages.

4. Select your installation folder

Specify the folder where you want Eclipse to be installed. The default folder will be in your User directory.

Select the ‘Install’ button to begin the installation.

Screenshot of the Install window.

5. Launch Eclipse

Once the installation is complete you can now launch Eclipse. The Eclipse Installer has done it's work. Happy coding.

Screenshot of the Launch window.

...or download an Eclipse Package

Eclipse IDE for Java EE Developers

Eclipse IDE for Java EE Developers

  • 273 MB
  • 1,850,647 DOWNLOADS

Tools for Java developers creating Java EE and Web applications, including a Java IDE, tools for Java EE, JPA, JSF, Mylyn...

Run your Apps on the Cloud

Want Eclipse in the cloud? IBM Bluemix makes it easy. Sign up to begin building today!

Eclipse IDE for Java Developers

Eclipse IDE for Java Developers

  • 165 MB
  • 908,477 DOWNLOADS

The essential tools for any Java developer, including a Java IDE, a Git client, XML Editor, Mylyn, Maven integration and WindowBuilder...

Eclipse IDE for C/C++ Developers

Eclipse IDE for C/C++ Developers

  • 182 MB
  • 373,036 DOWNLOADS

An IDE for C/C++ developers with Mylyn integration.

Eclipse IDE for Eclipse Committers 4.5.1

Eclipse IDE for Eclipse Committers 4.5.1

  • 243 MB
  • 264,159 DOWNLOADS

Package suited for development of Eclipse itself at Eclipse.

Eclipse for PHP Developers

Eclipse for PHP Developers

  • 152 MB
  • 244,573 DOWNLOADS

The essential tools for any PHP developer, including PHP language support, Git client, Mylyn and editors for JavaScript, HTML, CSS and...

Eclipse IDE for Java and DSL Developers

Eclipse IDE for Java and DSL Developers

  • 295 MB
  • 157,313 DOWNLOADS

The essential tools for Java and DSL developers, including a Java & Xtend IDE, a DSL Framework (Xtext), a Git client.

Eclipse IDE for Automotive Software Developers

Eclipse IDE for Automotive Software Developers

  • 235 MB
  • 137,029 DOWNLOADS

This package contains frameworks and tools used for the development of embedded automotive software: In addition to Eclipse Platform, Java Development...

Eclipse for RCP and RAP Developers

Eclipse for RCP and RAP Developers

  • 257 MB
  • 132,249 DOWNLOADS

A complete set of tools for developers who want to create Eclipse plug-ins, Rich Client Applications or Remote Application Platform (RCP+RAP).

Eclipse Modeling Tools

Eclipse Modeling Tools

  • 363 MB
  • 129,097 DOWNLOADS

The Modeling package provides tools and runtimes for building model-based applications.

Eclipse IDE for Java and Report Developers

Eclipse IDE for Java and Report Developers

  • 298 MB
  • 127,157 DOWNLOADS

Java EE tools and BIRT reporting tool for Java developers to create Java EE and Web applications that also have reporting...

Eclipse for Parallel Application Developers

Eclipse for Parallel Application Developers

  • 225 MB
  • 118,544 DOWNLOADS

Tools for C, C++, Fortran, and UPC, including MPI, OpenMP, OpenACC, a parallel debugger, and remotely building, running and monitoring applications...

Eclipse for Testers

Eclipse for Testers

  • 116 MB
  • 116,335 DOWNLOADS

This package contains Eclipse features that support the software development quality assurance process, such as Jubula and Mylyn.

Eclipse for Scout Developers

Eclipse for Scout Developers

  • 312 MB
  • 110,889 DOWNLOADS

Eclipse Scout is a framework to develop Java/Eclipse based business applications that run on the desktop, in browsers, and on mobile.

Hint

You will need a Java runtime environment (JRE) to use Eclipse (Java SE 7 or greater is recommended). All downloads are provided under the terms and conditions of the Eclipse Foundation Software User Agreement unless otherwise specified.

Back to the top

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/simplefile0000664000000000000000000000001413013560574021436 0ustar foo bar baz ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/0000775000000000000000000000000013013560574023562 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/0000775000000000000000000000000013013560574025361 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/8.0.42/0000775000000000000000000000000013013560574026112 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/8.0.42/final/0000775000000000000000000000000013013560574027203 5ustar ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/8.0.42/final/zip/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/8.0.42/final/zip0000775000000000000000000000000013013560574027726 5ustar ././@LongLink0000644000000000000000000000020600000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/8.0.42/final/zip/netbeans-8.0.42-201411181905.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/download.netbeans.org/netbeans/8.0.42/final/zip0000664000000000000000000000135313013560574027732 0ustar PK!bG netbeans/PKBbG netbeans/bin/PK QD$netbeans/bin/java-fake#!/bin/sh sleep 60 PK ,E:///netbeans/bin/netbeans#!/bin/sh $(dirname $0)/java-fake -arch i686 PK/bG netbeans/nb/PK /bGnetbeans/nb/netbeans.pngPK?!bG Anetbeans/PK?BbG A'netbeans/bin/PK? QD$ Rnetbeans/bin/java-fakePK? ,E:/// netbeans/bin/netbeansPK?/bG Anetbeans/nb/PK? /bG &netbeans/nb/netbeans.pngPKy\ubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/0000775000000000000000000000000013013560574023337 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/0000775000000000000000000000000013013560574023667 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/0000775000000000000000000000000013013560574026212 5ustar ././@LongLink0000644000000000000000000000021000000000000011574 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Linux-Release-Notes-and-Known-Issues/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Li0000775000000000000000000000000013013560574030217 5ustar ././@LongLink0000644000000000000000000000021400000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Linux-Release-Notes-and-Known-Issues/m-p/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Li0000775000000000000000000000000013013560574030217 5ustar ././@LongLink0000644000000000000000000000022400000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Linux-Release-Notes-and-Known-Issues/m-p/2323665/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Li0000775000000000000000000000000013013560574030217 5ustar ././@LongLink0000644000000000000000000000023600000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Linux-Release-Notes-and-Known-Issues/m-p/2323665/index.htmlubuntu-make-16.11.1ubuntu1/tests/data/server-content/community.unity.com/t5/Linux-Editor/Unity-on-Li0000664000000000000000000121673713013560574030242 0ustar Unity on Linux: Release Notes and Known Issues - Unity3d Community Unity
Showing results for
Search instead for
Did you mean:
Reply
Highlighted
N/A

See more topics labeled with:

Unity on Linux: Release Notes and Known Issues

Hi! This thread will be used to post new builds of Unity for Linux, including release notes and known issues.

THE LATEST AVAILABLE BUILD WILL BE IN THE LAST POST ON THIS THREAD.

Today, we're releasing the first public build, so this post contains extra information about system requirements and what you can expect. Future releases will also be posted in this thread.

Installer Types and Supported Systems

The Unity Editor for Linux is packaged into two types of installers:


  • A .deb package, which can be installed via the Ubuntu Software Center and is expected to work on installations of Ubuntu 12.04 or newer.
  • A platform-agnostic self-extracting shell script, which is designed for other distributions.

Unity Technologies is providing official support for Ubuntu 12.04 or newer. People are welcome to use other distributions with the understanding that we do not guarantee support.

Machines also need a modern graphics card with vendor-supported graphics drivers (provided by NVIDIA, AMD, or Intel).

We do not explicitly support running the Linux editor inside a virtual machine due to limitations related to GPU virtualization (although it does usually work).

Supported Target Platforms
The Unity Editor for Linux supports export to the following platforms:

  • Linux / Windows / Mac Standalone
  • Android (additional dependencies needed, see below)
  • WebGL (additional dependencies needed, see below)
  • Tizen (additional dependencies needed, see below)
  • SamsungTV
  • Legacy WebPlayer

Dependencies and Recommended Packages
The dependencies for Unity itself are:

  • gconf-service
  • lib32gcc1 (>= 1:4.1.1)
  • lib32stdc++6 (>= 4.6)
  • libasound2 (>= 1.0.23)
  • libc6 (>> 2.15)
  • libc6-i386 (>= 2.15)
  • libcairo2 (>= 1.6.0)
  • libcap2 (>= 2.10)
  • libcups2 (>= 1.4.0)
  • libdbus-1-3 (>= 1.2.14)
  • libexpat1 (>= 1.95.8)
  • libfontconfig1 (>= 2.8.0)
  • libfreetype6 (>= 2.3.9)
  • libgcc1 (>= 1:4.1.1)
  • libgconf-2-4 (>= 2.31.1)
  • libgdk-pixbuf2.0-0 (>= 2.22.0)
  • libgl1-mesa-glx | libgl1
  • libglib2.0-0 (>= 2.31.8)
  • libglu1-mesa | libglu1
  • libgtk2.0-0 (>= 2.24.0)
  • libnspr4 (>= 1.8.0.10)
  • libnss3 (>= 3.14.3)
  • libpango1.0-0 (>= 1.22.0)
  • libstdc++6 (>= 4.6)
  • libx11-6 (>= 2:1.4.99.1)
  • libxcomposite1 (>= 1:0.3-1)
  • libxcursor1 (>> 1.1.2)
  • libxdamage1 (>= 1:1.1)
  • libxext6
  • libxfixes3
  • libxi6 (>= 2:1.2.99.4)
  • libxrandr2 (>= 2:1.2.99.2)
  • libxrender1
  • libxtst6
  • zlib1g (>= 1:1.1.4)
  • debconf (>= 0.5) | debconf-2.0

The Ubuntu Software Center will install these automatically if using the .deb package. If using the self-extracting shell script (or another distribution), you're on your own.

To export players to certain targets, there are other dependencies:

For WebGL:


  • ffmpeg | libav-tools
  • nodejs
  • java6-runtime
  • gzip

For Android and Tizen:

  • java7-jdk

These recommended packages are included in the Recommends section of the .deb package.

We're also not currently bundling the dependencies for MonoDevelop (and doing so is a bit complicated), so the easiest way to ensure you can run the bundled MonoDevelop is to first install the upstream MonoDevelop from the Ubuntu Software Center.

Reporting Bugs

The 'Report a Bug' link currently directs users to this area of the forum, which is dedicated to feedback and issues with the Linux Editor. This is the primary location for providing feedback and reporting issues with the Linux Editor.

Crashes will launch the bug reporter, and you should use this to submit a bug in this case (the bug reporter attaches stacktrace and other information we need to investigate crashes). After submitting your bug with the bug reporter, please post on the forum with the case number you receive in your confirmation mail.


And finally, here is the information for today's release:

Build #2015082501

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/unity-editor-5.1.0f3+2015082501_amd64.deb

Unsupported Installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/unity-editor-installer-5.1.0f3+2015082501.sh

Release Notes

  • Initial release

Known Issues

The Linux Editor currently has some known issues:


  • The asset store window cannot be docked into the main editor window
  • Drag and drop between separate editor windows (e.g build settings window and main editor window) does not work
  • Drag and drop from outside the application does not work
  • Moving/Dragging undocked editor windows doesn't feel native yet
  • Context menus at the bottom of the screen have unintuitive initial scroll position
  • "Open in Unity" doesn't work when browsing the Asset Store from an external browser
  • Idle CPU usage is higher than it should be.
  • Certain systems may experience "Service unavailable" errors when trying to log in. WORKAROUND: Launch Unity with LD_PRELOAD=/usr/lib/libresolv.so.2 /path/to/Unity (check the path to your local libresolv) (Kudos to spacepluk and the other hardcore investigators!)

Unity on Linux: Release Notes and Known Issues

Hello lovely people! We have prepared a new build for you. Links and release notes below. Happy testing!

Build #2015090301

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/unity-editor-5.1.0f3+2015090301_amd64.deb

Unsupported Installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/unity-editor-installer-5.1.0f3+2015090301.sh

Release Notes

  • Fix login autofail for some users (depend on system libpq5, don't ship conflicting libs)
  • Allow mouse capture in game view

  • Fix context menus in Animator window

  • Allow interaction with game view header UI in play mode

  • Set default new-project location to XDG_DOCUMENTS_DIR

Unity on Linux: Release Notes and Known Issues

Hi again lovely people! We have prepared another build for you. Happy testing!

Build #2015091501

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/unity-editor-5.1.0f3+2015091601_amd64.deb

Unsupported Installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/unity-editor-installer-5.1.0f3+2015091501.sh

Release Notes

  • Make reported mouse offsets consistent everywhere
  • Fix direction of mouse scroll delta in play mode
  • Report mouse button events when cursor is locked in play mode
  • Support "Open in Unity" for Asset Store packages (opens new Unity instance for now)
  • Fix Asset Store for comma-decimal locales
  • Make popups less prone to inadvertently close
  • Fix shift+key in game view
  • Don't crash on first run if XDG user directories aren't configured
  • Fix interaction with Sprite Editor slice dropdown
  • Fix intermittent crashes when opening/closing child windows
  • Don't double-report IMGUI key events in play mode
  • Fix initialization of fixed-size child windows (color picker)
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

It's been a while, but hopefully it will have been worth it.

Build #2015101801

Official Installer for 64-bit Ubuntu Linux:
http://files.unity3d.com/levi/unity-editor-5.2.2f1+20151018_amd64.deb

Unsupported Installer for Other 64-bit Distributions:
http://files.unity3d.com/levi/unity-editor-installer-5.2.2f1+20151018.sh

Release Notes

  • Update to Unity 5.2.2f1
  • Avoid crash when creating input context fails at startup
  • Make WebGL build output directory layout match the one generated on other platforms
  • Don't leak file handles when communicating with external processes (e.g. audio importer)
  • Known issue: There's a small regression in cursor offset handling in the game view
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Some known issues in this one, but we wanted to give everybody a chance to play with it over the winter holidays. Enjoy, and we'll see you next year!

Build #2015121801

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/linux/unity-editor-5.3.0f4+20151218_amd64.deb (sha1sum 282ca0f7bd25dc2d3f0a1f9d493ecffe9bb9fb36)

Unsupported installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.0f4+20151218.sh (sha1sum f38ea2b578ac37eacc97440966a42bc17d7b6f81)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.3.0f4+20151218.torrent

Release Notes

  • Update to Unity 5.3.0f4
  • Update to MonoDevelop 5.9
  • All fixes reported for build #2015101801
  • Keyboard input for web views should behave similarly to Unity 5.1 builds

  • Known issue: Cursor offset in game view is still present
  • Known issue: MonoDevelop's application icon is missing
  • Editor still uses legacy OpenGL rendering backend on Linux
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016010601

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/linux/unity-editor-5.3.1f1+20160106_amd64.deb
(sha1sum
6636dbd9350a0589fd23bd7643fba99c8fb83685)

Unsupported installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.1f1+20160106.sh
(sha1sum
4438875861bbddd18a68230c4062e79cd6139c2f)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.3.1f1+20160106.torrent

Release Notes

  • Update to Unity 5.3.1
  • Force harder to OpenGL legacy mode for now
  • Improve web view integration (focus, docking, resizing)
  • Improve cursor position reporting in game view
  • Fix cursor position offset when game view is letterboxed
  • Fix keypresses (e.g. arrows) in game view changing keyboard focus
  • Fix "Add Resolution" popup for game view
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016020801

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/linux/unity-editor-5.3.2f1+20160208_amd64.deb
(sha1sum
6e4f92b024a603a289965fd16b9ba3513f461590)

Unsupported installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.2f1+20160208.sh
(sha1sum
7bae74f50050e326594133c8115c3094b97eb8d5)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.3.2f1+20160208.torrent

Release Notes

  • Update to Unity 5.3.2
  • Fix "gray webview panel" on first start
  • Fix VR publishing for supported platforms (e.g. GearVR)
  • Fix menu item invocation after play/stop cycle
  • Make file extension filtering case insensitive (e.g. unityPackage)
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016022301

Official Installer for 64-bit Ubuntu Linux:
http://download.unity3d.com/download_unity/linux/unity-editor-5.3.3f1+20160223_amd64.deb
(sha1sum
e31b684d14d890f09073d57ca1f07a96a8814265)

Unsupported installer for Other 64-bit Distributions:
http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.3f1+20160223.sh
(sha1sum
3e6129bcc195303773896ddf667db2f9df4c5fd3)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.3.3f1+20160223.torrent

Release Notes

  • Update to Unity 5.3.3
  • Fix importing Unity packages from project browser
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016031601

This one's a double feature!
Yesterday at GDC, we announced public beta access for Unity 5.4, and you won't be left out!

Official Installers for 64-bit Ubuntu Linux:
5.3.4f1: http://download.unity3d.com/download_unity/linux/unity-editor-5.3.4f1+20160316_amd64.deb
(sha1sum
e855743ec80241f54db3a349b3a68a93365c20dd)
5.4.0b10: http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b10+20160316_amd64.deb
(sha1sum b29f9d8fe9bcbfe5d1759003c10e66aa66e54f8a)

Unsupported installer for Other 64-bit Distributions:
5.3.4f1: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.4f1+20160316.sh
(sha1sum
98cc96e82c5d8703c954ebcdffc392c5e790b5cd)
5.4.0b10: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b10+20160316.sh
(sha1sum 8465fee80eff49595a0f172ce77d35398423dd74)

Torrent (Includes both installers):
5.3.4f1: http://files.unity3d.com/levi/unity-editor-5.3.4f1+20160316.torrent
5.4.0b10: http://files.unity3d.com/levi/unity-editor-5.4.0b10+20160316.torrent

Release Notes: 5.3.4f1

  • Update to Unity 5.3.4 (includes lots of OpenGL Core fixes for linux)


Release Notes: 5.4.0b10
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016031701

Official Installers for 64-bit Ubuntu Linux:
5.3.4f1: http://download.unity3d.com/download_unity/linux/unity-editor-5.3.4f1+20160317_amd64.deb
(sha1sum
886b5a776c40df30114223fc7075d8b9e23a1548)
5.4.0b10: http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b10+20160317_amd64.deb
(sha1sum 863418e077688a3f4b5e276c75168518a494bc24)

Unsupported installer for Other 64-bit Distributions:
5.3.4f1: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.4f1+20160317.sh
(sha1sum
7b1961fdbe52ccf3e3d567bc6b7211165a263238)
5.4.0b10: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b10+20160317.sh
(sha1sum 8c40895ccdb86c18943e0e72d1d8aca57a9a72ac)

Torrent (Includes both installers):
5.3.4f1: http://files.unity3d.com/levi/unity-editor-5.3.4f1+20160317.torrent
5.4.0b10: http://files.unity3d.com/levi/unity-editor-5.4.0b10+20160317.torrent

Release Notes:

  • Really actually fix "gray welcome window" issue
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016040601

Official Installers for 64-bit Ubuntu Linux:
5.4.0b13:
http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b13+20160406_amd64.deb
(sha1sum 2751b591ad3624ed044231f8a16a008a6aa2c5eb)

Unsupported installer for Other 64-bit Distributions:
5.4.0b13: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b13+20160406.sh
(sha1sum 2ef79bb4923fe706327e95b8f83e9a076819af4b)

Torrent (Includes both installers):
5.4.0b13: http://files.unity3d.com/levi/unity-editor-5.4.0b13+20160406.torrent

Release Notes:

  • 5.4.0b13
  • Fix vertically-flipped mouse position reporting in Linux standalone
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016041801

Official Installers for 64-bit Ubuntu Linux:
5.4.0b15:
http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b15+20160418_amd64.deb
(sha1sum db2379f936be8d40bcf30cffd3664880d9678d9c)

Unsupported installer for Other 64-bit Distributions:
5.4.0b15: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b15+20160418.sh
(sha1sum 1e94a64a42fc4c92fb405b0b4493025c9074f4bc)

Torrent (Includes both installers):
5.4.0b15: http://files.unity3d.com/levi/unity-editor-5.4.0b15+20160418.torrent

Release Notes:

  • 5.4.0b15
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016050301

Official Installers for 64-bit Ubuntu Linux:
5.3.4f1: http://download.unity3d.com/download_unity/linux/unity-editor-5.3.4f1+20160503_amd64.deb
(sha1sum 62868041a95a802f4d59626093548dc93872c69f)
5.4.0b16: http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b16+20160503_amd64.deb
(sha1sum b8b0e7963947a002e5fbeb9102e2e0be3a0bf756)

Unsupported installer for Other 64-bit Distributions:
5.3.4f1: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.4f1+20160503.sh
(sha1sum 2a7b0eb5e0d4d7af107fa2f7146c5564230ea778)
5.4.0b16: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b16+20160503.sh
(sha1sum 96dd447d5ba75f30205eac8dd7c93a76b09546c1)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.4.0b16+20160503.torrent

Release Notes:

  • Fix crash when closing auxiliary windows
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016052501

Official Installers for 64-bit Ubuntu Linux:
5.3.5f1: http://download.unity3d.com/download_unity/linux/unity-editor-5.3.5f1+20160525_amd64.deb
(sha1sum db9c7253d12393543099894a9d2ea523ff7a3b60)
5.4.0b18: http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b18+20160524_amd64.deb
(sha1sum a52f4d94233facba1624140a9e5733178c5a4222)

Unsupported installer for Other 64-bit Distributions:
5.3.5f1: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.3.5f1+20160525.sh
(sha1sum c9c96baf6b2c1351b83ea2984e0dfa4050d6bce2)
5.4.0b18: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b18+20160524.sh
(sha1sum a4207fdcb8d5cea66c21e81778e6345f2633b520)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.3.5f1+20160525.torrent
http://files.unity3d.com/levi/unity-editor-5.4.0b18+20160525.torrent

Release Notes:

  • Update to 5.3.5f1/5.4.0b18
  • 5.4: Fix WebGL deployment
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016060901

Official Installers for 64-bit Ubuntu Linux:
5.4.0b21:
http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b21+20160609_amd64.deb
(sha1sum 49555ea7bf8075878d2701203ffc343897d0d909)

Unsupported installer for Other 64-bit Distributions:
5.4.0b21:
http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b21+20160609.sh
(sha1sum d09b743694da1418dec36ead6a6fc1bf087e246f)

Torrent (Includes both installers):
http://files.unity3d.com/levi/unity-editor-5.4.0b21+20160609.torrent

Release Notes:

  • Update to 5.4.0b21
Unity Technologies
Unity Technologies

Unity on Linux: Release Notes and Known Issues

Build #2016062801

Official Installers for 64-bit Ubuntu Linux:
5.4.0b23: http://download.unity3d.com/download_unity/linux/unity-editor-5.4.0b23+20160628_amd64.deb
(sha1sum 7f92d9a98d1990d768d72d3d882ce96da46f1efa)

Unsupported installer for Other 64-bit Distributions:
5.4.0b23: http://download.unity3d.com/download_unity/linux/unity-editor-installer-5.4.0b23+20160628.sh
(sha1sum ef83d577413153873495e6e355cd230796533c91)

Torrent (Includes both installers): http://files.unity3d.com/levi/unity-editor-5.4.0b23+20160628.torrent


Release Notes:

  • Update to 5.4.0b23
ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/0000775000000000000000000000000013013560574021426 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/0000775000000000000000000000000013013560574023445 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/0000775000000000000000000000000013013560574025464 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/0000775000000000000000000000000013013560574027267 5ustar ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/download/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/downl0000775000000000000000000000000013013560574030333 5ustar ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/download/mock/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/downl0000775000000000000000000000000013013560574030333 5ustar ././@LongLink0000644000000000000000000000021200000000000011576 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/download/mock/lighttable-mock-linux.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/LightTable/LightTable/releases/downl0000664000000000000000000000045413013560574030340 0ustar *VKj0)N5z.e/*rڡ]8J\R}K|FV/Ͼ|;[ښmi:Z4 -}k=W4{ Z2{AG%$+#hǭT-}<ǭܬô6n_/rKs/;z5Ny9c 俽Dz[/Q1X44ca1Œ,"#?Uyf bH$?Wubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/0000775000000000000000000000000013013560574022366 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/atom/0000775000000000000000000000000013013560574023326 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/atom/releases/0000775000000000000000000000000013013560574025131 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/atom/releases/download/0000775000000000000000000000000013013560574026740 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/atom/releases/download/mock/0000775000000000000000000000000013013560574027671 5ustar ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/atom/releases/download/mock/atom-amd64.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/atom/atom/releases/download/mock/ato0000664000000000000000000000032513013560574030377 0ustar )zWM 0{kms(EՊ񍺨.čULHζrSPYRuX+ :mu iѱAJJMT{tR.]٭kj/*SKU|5|@z|[KCpԐcr10x_mθ ki (ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/0000775000000000000000000000000013013560574023307 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/0000775000000000000000000000000013013560574024607 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/releases/0000775000000000000000000000000013013560574026412 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/releases/download/0000775000000000000000000000000013013560574030221 5ustar ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/releases/download/build-1.0.0/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/releases/download/b0000775000000000000000000000000013013560574030363 5ustar ././@LongLink0000644000000000000000000000021100000000000011575 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/releases/download/build-1.0.0/kotlin-compiler-1.0.0.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/github.com/JetBrains/kotlin/releases/download/b0000664000000000000000000000502613013560574030370 0ustar PK {XHkotlinc/UT VxVux PK EYH kotlinc/bin/UT xVxVux PKPPNHkotlinc/bin/kotlinc-jvmUT h VxVux eAo0)!H+e{Y*ۊH!mգ1lmJ;jE\ X.vt9Z7Ւ_?7;+H9ptXLzU $FH' xEH+V0y^ݲQЉ#(w䠢R ugZJ" 阳 cB@'{3ai[It͒a'j9'1#,RL؊Q[#`ɓta]JrRoE#_\P&9ywI xKۗ=%]M}O )\cG~B,Ǿro>9*KսjVq0h;rE:+٥ /%Y%:Аlg^Ѿ%%yW|PKEYHG kotlinc/bin/kotlincUT xVxVux Mo@WӤ' FxhPmEoL2Ofƙ;U=tp'C-<*l=emCR+|=0<],L$[^_@E} 9 c9\I4_v?:\fq26cAV9[)8.%9oF#z_ URC!yO1}voqKV9d[Xf]KW_!N`wS@nck~XȵhOU'+ʼ\hA:+٥yǝAv$̾H6gnxF_WI6!-TCى>_y6«뒬2W}MyxOt>xKPKPPNHKfضkotlinc/bin/kotlinUT h VxVux eo0+n@Zi/&U&Fl6#{Lj5!}$Rk,|q#=eY.4m Swift.org - Download Swift

Download Swift

Latest Development Snapshots

Development Snapshots are prebuilt binaries that are automatically created from mainline development branches. These snapshots are not official releases. They have gone through automated unit testing, but they have not gone through the full testing that is performed for official releases.

Platform Download Date
Apple Platforms Xcode Swift 2.2 Snapshot Debugging Symbols
Linux Ubuntu 15.10 Swift 2.2 Snapshot Signature
Linux Ubuntu 14.04 Swift 2.2 Snapshot Signature

Swift is covered by the Swift License at swift.org/LICENSE.txt.

Apple Platforms

Xcode includes a release of Swift that is supported by Apple. You can try out a version that is still in development by downloading one of the packages above.

Playgrounds are not currently supported for downloadable Swift packages.

To submit to the App Store you must build your app using the version of Swift that comes included within Xcode.

Requirements for Tools

  • OS X 10.11 (El Capitan)
  • Xcode 7.2 (including prerelease versions)

Supported Target Platforms

  • OS X 10.9.0 or later
  • iOS 7.0 or later
  • watchOS 2.0 or later
  • tvOS 9.0 or later

Installation

  1. Download the latest package release.

  2. Run the package installer, which will install an Xcode toolchain into /Library/Developer/Toolchains/.

    An Xcode toolchain (.xctoolchain) includes a copy of the compiler, lldb, and other related tools needed to provide a cohesive development experience for working in a specific version of Swift.

  3. Quit Xcode if it is already running.

  4. Start Xcode with the custom toolchain you downloaded to enable the open source version of Swift:

    $ xcrun launch-with-toolchain /Library/Developer/Toolchains/swift-latest.xctoolchain
    

    swift-latest.xctoolchain is a symlink to your most recently installed toolchain, such as swift-2.2-SNAPSHOT-2015-12-01-a.xctoolchain. The name of each toolchain indicates the date the toolchain was built from the open source master branch (which tracks bleeding-edge development on Swift).

    Within a running instance of Xcode launched with launch-with-toolchain, Xcode uses the downloaded toolchain for building Swift code, debugging, and even code completion and syntax coloring. If you quit Xcode, you must relaunch it with launch-with-toolchain to continue using the downloaded toolchain; otherwise, Xcode uses its default toolchain the next time you launch it.

  5. To use the Swift tools directly from the command line, add the Swift toolchain to your path as follows:

    $ export PATH=/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin:"${PATH}"
    

Code Signing on OS X

The OS X .pkg files are digitally signed by the developer ID of the Swift open source project to allow verification that they have not been tampered with. All binaries in the package are signed as well.

The Swift toolchain installer on OS X should display a lock icon on the right side of the title bar. Clicking the lock brings up detailed information about the signature. The signature should be produced by Developer ID Installer: Swift Open Source (V9AUD2URP3).

If the lock is not displayed or the signature is not produced by the Swift open source developer ID, do not proceed with the installation. Instead, quit the installer and please email swift-infrastructure@swift.org with as much detail as possible, so that we can investigate the problem.

Older Releases

Download Date
Xcode Swift 2.2 Snapshot Debugging Symbols
Xcode Swift 2.2 Snapshot Debugging Symbols
Xcode Swift 2.2 Snapshot Debugging Symbols
Xcode Swift 2.2 Snapshot Debugging Symbols
Xcode Swift 2.2 Snapshot Debugging Symbols
Xcode Swift 2.2 Snapshot Debugging Symbols

Linux

Packages for Linux are tar archives including a copy of the Swift compiler, lldb, and related tools. You can install them anywhere as long as the extracted tools are in your PATH.

Note that nothing prevents Swift from being ported to other Linux distributions beyond the ones mentioned below. These are only the distributions where these binaries have been built and tested.

Requirements

  • Ubuntu 14.04 or 15.10 (64-bit)

Supported Target Platforms

  • Ubuntu 14.04 or 15.10 (64-bit)

Older Releases

Download Date
Ubuntu 15.10 Swift 2.2 Snapshot Signature
Ubuntu 15.10 Swift 2.2 Snapshot Signature
Ubuntu 15.10 Swift 2.2 Snapshot Signature
Ubuntu 15.10 Swift 2.2 Snapshot Signature
Ubuntu 15.10 Swift 2.2 Snapshot Signature
Ubuntu 15.10 Swift 2.2 Snapshot Signature
Download Date
Ubuntu 14.04 Swift 2.2 Snapshot Signature
Ubuntu 14.04 Swift 2.2 Snapshot Signature
Ubuntu 14.04 Swift 2.2 Snapshot Signature
Ubuntu 14.04 Swift 2.2 Snapshot Signature
Ubuntu 14.04 Swift 2.2 Snapshot Signature
Ubuntu 14.04 Swift 2.2 Snapshot Signature

Installation

  1. Install required dependencies:

    $ sudo apt-get install clang libicu-dev
    
  2. Download the latest binary release above.

    The swift-<VERSION>-<PLATFORM>.tar.gz file is the toolchain itself. The .sig file is the digital signature.

  3. If you are downloading Swift packages for the first time, import the PGP keys into your keyring:

    $ gpg --keyserver hkp://pool.sks-keyservers.net \
          --recv-keys \
          '7463 A81A 4B2E EA1B 551F  FBCF D441 C977 412B 37AD' \
          '1BE1 E29A 084C B305 F397  D62A 9F59 7F4D 21A5 6D5F'
    

    or:

    $ wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -
    

    Skip this step if you have imported the keys in the past.

  4. Verify the PGP signature.

    The .tar.gz archives for Linux are signed using GnuPG with one of the keys of the Swift open source project. Everyone is strongly encouraged to verify the signatures before using the software.

    First, refresh the keys to download new key revocation certificates, if any are available:

    $ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift
    

    Then, use the signature file to verify that the archive is intact:

    $ gpg --verify swift-<VERSION>-<PLATFORM>.tar.gz.sig
    ...
    gpg: Good signature from "Swift Automatic Signing Key #1 <swift-infrastructure@swift.org>"
    

    If gpg fails to verify because you don’t have the public key (gpg: Can't check signature: No public key), please follow the instructions in Active Signing Keys below to import the keys into your keyring.

    You might see a warning:

    gpg: WARNING: This key is not certified with a trusted signature!
    gpg:          There is no indication that the signature belongs to the owner.
    

    This warning means that there is no path in the Web of Trust between this key and you. The warning is harmless as long as you have followed the steps above to retrieve the key from a trusted source.

    If gpg fails to verify and reports “BAD signature”, do not use the downloaded toolchain. Instead, please email swift-infrastructure@swift.org with as much detail as possible, so that we can investigate the problem.

  5. Extract the archive with the following command:

    $ tar xzf swift-<VERSION>-<PLATFORM>.tar.gz
    

    This creates a usr/ directory in the location of the archive.

  6. Add the Swift toolchain to your path as follows:

    $ export PATH=/path/to/usr/bin:"${PATH}"
    

    You can now execute the swift command to run the REPL or build Swift projects.

Active Signing Keys

The Swift project uses one set of keys for snapshot builds, and separate keys for every official release. We are using 4096-bit RSA keys.

The following keys are being used to sign toolchain packages:

  • Swift Automatic Signing Key #1 <swift-infrastructure@swift.org>

    Download
    https://swift.org/keys/automatic-signing-key-1.asc
    Fingerprint
    7463 A81A 4B2E EA1B 551F FBCF D441 C977 412B 37AD
    Long ID
    D441C977412B37AD

    To import the key, run:

    $ gpg --keyserver hkp://pool.sks-keyservers.net \
          --recv-keys \
          '7463 A81A 4B2E EA1B 551F  FBCF D441 C977 412B 37AD'
    

    Or:

    $ wget -q -O - https://swift.org/keys/automatic-signing-key-1.asc | gpg --import -
    
  • Swift 2.2 Release Signing Key <swift-infrastructure@swift.org>

    Download
    https://swift.org/keys/release-key-swift-2.2.asc
    Fingerprint
    1BE1 E29A 084C B305 F397 D62A 9F59 7F4D 21A5 6D5F
    Long ID
    9F597F4D21A56D5F

    To import the key, run:

    $ gpg --keyserver hkp://pool.sks-keyservers.net \
          --recv-keys \
          '1BE1 E29A 084C B305 F397  D62A 9F59 7F4D 21A5 6D5F'
    

    Or:

    $ wget -q -O - https://swift.org/keys/release-key-swift-2.2.asc | gpg --import -
    

Swift and the Swift logo are trademarks of Apple Inc.

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/keys/0000775000000000000000000000000013013560574022264 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/keys/all-keys.asc0000664000000000000000000001020613013560574024474 0ustar -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQMuBFaXW+IRCACzauJ23sc/ca4OEjdDEkOkfaXHN1vR24Twjh8St0WiPjxJDd2W XsczwBuSBr2Fp5r+OLJ1FVwyXj1Rwb/yAGn9SUMXRxP4JLkwuBk2WHQqj3fv9ekI 91iWngezQKmpIs0K0srHRn+RbZoN2CtA+x10yotqhghjStVHvArWoUlYwwhpb+/k IqjH7UGIr8hMWivLiqFD8ZjLlxu/Eohw7QKaEo5M7B/aPNM1+YCWOVTH0v7kaCnH LoO2ELaMf4FFLPmk2At5ffqddpfwGF8KLC3YChExMME5Ko56somO1TeGzAA1TVO1 zuQxwCLXhNO856PK4tYzWZAENeRqAMMXY3v7AQCb7+PoeHTTmJPYwA0b1cEtEoLR 9WfWyEekXwkbLqiDAwf/Yzj1+57NGzeo/18LEJdwpe03i0/8Rtw1tXstHeskCr0x J2BpsKdUZQuMj/YxIujFiIKU+rt7DQbTUANACwWetSldJwe7EpO4rxXIJjajSD9l V5JQo02SiFemlbgZZX+zZp4cJXpcpji2wUY7PZeAzKyqDq83O1Fw2wiBLf6Hj7EA f0sTY2q3HMAcwRLjrwf06ZjpdDlwPyqoyK2iWVygcyRS6jSB8lZC/76UEYdt5IjF kEV8/cuyOlNc6nyFNf1wKBpXfuQ2MxzSZCVdJc017DHKNM4qFgreFFrWCU3ePQGR e9wuXETshGaeuYGypEB252jDG2sN6yjFv9R706uKTAf8CyIkWLF0AbHTVOk123Lw SWBqMTs5KbESdRMFKH4FXO05gpxo+iUZNoucQ7kQkfH1MkkK2+1HhyEUZtzktPaJ /OqQRbXjg/XUpHQjRcV9Vbh0nyguBAWp+Ao7zQ+ZhgZrC+mbjiF7YXXvQpcwXRom 9KXVeCeVMt/syh65MU9aYQZ+0HyUCVSNHsfshMWul/SFLL1FTFjkaqHDOY0f+xOa duYkSB7ryml8fcClzp+iUnrGm6I8MWo9pOXH6nMZ4qhhL6+szH2JcpmOEtZJ+ZG7 aeBUhw1s5NP+lhmPOata4jTuu5b6huKpGR6ztjsZ2uMLXRbgXMVeBJI3KHf+RUeu wLQZIDx1YnVudHUtbWFrZUB1YnVudHUuY29tPoh6BBMRCAAiBQJWl1viAhsjBgsJ CAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDqEPHixeB24v2/AQCF7SWqcmhpLgaI OWq/2o3bg9AJIpj0TY3wdcCWAY1DMAD+M8o54KR3Ry2lP6TgEAYp8I7UwDsSwzsh rpyOv/lO9xs= =Ul87 -----END PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQMuBFaXXNgRCACd6Z5MSnPFIowD8V8lyLJogsD4NDSksXhWV0YsWGrdEG67RHCl X5YxBOfVQaBJQWxCcv5IxAZjetn6HdCmEruSiwcW0NXlJ/oFlrGEk9qkVHgTpibC mBYcEJ9Pb1awGJorGgZ9QnM0B5C0oTgK3ySItw8lQVd/4bAkda3+JGaJ2GWnN5mZ UmHXR61Q7K2Yrn3/D4SCaPB2qxqtwWtP93n8QLg9c/xf9L5CUi34i12UI/bCpTDO rc5meDPzNCTzayoj0op+TlI6C0N0V//Q5fKUtmC4zT3WUSkknzqgflMXc0YZy8MN V7dN4ATDNQt/oNb2TEBEnOJfNBmXPLr7E/wzAQD5ghRe0iJ8BXYz3ruHm6WGlTs+ E/CU8Jv7VBBIwkPWEwf/Qffretyi0FIk/UZhbGE70LQg4Fu8WllPa8R0SlwXP3// XQUjD4MMXLtwXj+ZwiLOE+PIYGgGp1ZBJdybJq8jsnahlTQ4W4Gd8KUgz8UadcIT 3U/5PFs3qzsHkbyYM2FSmVi9qhAkvyWT+WKLw3/xWnIH3+ngcV5IiU9MsaC6XsEw 1OhX3yDl2znZLHeIiJ1j1htJieBYgttG3MIFblQnber8hY0cAhxYpmhfigo5uyKi o1U651br6+1ORx8PiMGWk5DnmtnRRYKv7tThjV2OK08jfzo4+t4SYDR8W1pBzcpK Z1f+mtd0PBYs+dD56KD1Q7+BqSARK/KeUSNNkZ44FAf/R7zGwdTFAcwwBjZ9Hjg9 +oWdJvhHc4kX3nw7bfaR4T8tGBrQ54xl/vbIrF9MQDd85WZCpRYI8URgeHQiJFW6 wxV7YQk3oCrI6H5hzSmIs8+xyinZyCo1IOftToSCnsHsmkfAL946rPqDsKHwHMNj hF9xQxngKTmiSSCdkJH/ezwdO7t1+hvd6uK5bbnKSnCxzGp0ejHJ4f+X+IxFBSiU W9afBq9qpuRpunuAGnACUEbAKjKdulQcf2F/bkfQjIZvC0haLRNQWhcJ53Hn86B2 tAN8h5HDIHGmXxL7uiIrB0o35mdtyd2cRjOlZEHoRSoS2REUoYOLjren0K1e//Cx 67QZIDx1YnVudHUtbWFrZUB1YnVudHUuY29tPoh6BBMRCAAiBQJWl1zYAhsjBgsJ CAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBFhvcjsVa140SDAQDDBM8DRk57wd8z D4uzk+CjFBQP1skJBltT1tyEjhDW3QEAg0avQhGMFvsXfVOXPYgQLUu3+owNM85o tvXGXsYk7Sg= =a4tv -----END PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQMuBFaXqicRCACYFRlvi0qk7KyhajJUwFWhhrMgY+Cc3JLLr28PLbfEHoxLWPRT 1MFMVggu/GLFSaaJdczO0kJaXXhL+Gv5wr/eBeCKhHGJEg69rssQtBWtxF+I7bu1 Z37GvzKUa2UqWQqkQuSun3NTp2HtrB4u6H1TecDMQpGSQPYJ7tEOyRakku/75oQ3 cHGqhF4y4og9wUjkkMeeKn710N3CTuOGL+Ofk+LIEG6Fd6MAD3lFjv6cNUFwWH0b tW9xrt2x+H1wyb/ju+OFGW5kq12r4HACz0zBk/CMNxufFwUHykjC75d76F1aZEwT QO00/FHZx27FzcduXEXoTqvQ+AVUewrjWAo3AQCRT2Xg52cCODF2uW0qguOfijoA Ja3n+bfEpnd+zjvGZwf+O7G2TMx67XbS9O9Yo8Omz66qL4oFIydRZw1h4qiWmFjT FaBdc+M2Uxv6DJyj944ixyPGkSpuPNkuKIxplEfXncf0C7oK+hb+yyJwe8LsOx07 EOiaoi9hMggOAG4FuSuCJSPc60SXEIyqtDEDt0rhRWOfZAXdHI7LZQf3q+guJneN iVkOTvc3+YU5aH8RX3o4GuKBGTXUnuybRaew5yO/lIRfVUTnZocF3RmSCgtCyI3w /83y3kfb+Oegvpiy19WAmA4PIjcPFYuq24EbVxEYkQx9EFx0dyKG+sPuAFiYbLzS paRApa93NXEJ+ajJerTGrh/BUndf6is9tgYVuuTbPwgAlphh1XLE8FD2EiQ431XM 42DYFyxCHIGgpcrsS3tbRtwXJcZ1dx+uQeJ2xfWn+8/1aoh5Fcs6T9/GdMrr6z5h +FlVk4JXUzCiQfPnjLkrD91DMV1esu/KePio/wkY2r039AoZMEdhV6q0YQCxfr2z e8giUGJfHm6doOuX/S92J9iwulHkBt3k6acd+DNCnOkblVtOcrqmDKZ5/4CJwanR Icu/U3FgtZQFGeoDFWOuMucUZFkRwoItjN3QKzltsHvFVQufvdywnpRaoDUizOmM wOSrTH6yEDQaGdiARAiLQOovXpJbU/U5TG+ELVGKC+8gz5PwghHfeGeWM1T1zLJo 3bQZIDx1YnVudHUtbWFrZUB1YnVudHUuY29tPoh6BBMRCAAiBQJWl6onAhsjBgsJ CAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBFb331vWeFMbGDAP9V78C0Ean34cbs d9lmXaAZr5GZ/eeoFuXEglsLLJb1WAD/ff3JnfJ7m3r4mLP2jU4qIklC6XXi1VFd kIySjmCogXU= =GZp4 -----END PGP PUBLIC KEY BLOCK----- ubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/0000775000000000000000000000000013013560574022573 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/swift-mock-ubuntu15.10.tar.gz0000664000000000000000000000043213013560574027711 0ustar B6l4I`Jvȇ 11d$7M"j-G%~Gq%ҩ>x\C_9ɺOg,Q7?)KHGZʔf*.p6<+BL @o(v@W&ufxzUECS}am{ Ox3L'F__Y_j<@ I ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/swift-mock-ubuntu15.10.tar.gz.sigubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/swift-mock-ubuntu15.10.tar.gz.0000664000000000000000000000032513013560574027770 0ustar -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iF4EABEIAAYFAlaXqx4ACgkQRW999b1nhTFx0QD/bROb8zkxcG4CxtORFM4pWz0+ 12ZJYsDjKeKQ/NLb5KUA/jAgffKldSN8R3aFahLe34H6UTJ63aM6gjVH4NezEEnz =sVIk -----END PGP SIGNATURE----- ubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/swift-mock-ubuntu14.04.tar.gz0000777000000000000000000000000013013560574035026 2swift-mock-ubuntu15.10.tar.gzustar ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/swift-mock-ubuntu14.04.tar.gz.sigubuntu-make-16.11.1ubuntu1/tests/data/server-content/swift.org/builds/swift-mock-ubuntu14.04.tar.gz.0000777000000000000000000000000013013560574035665 2swift-mock-ubuntu15.10.tar.gz.sigustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/golang.org/0000775000000000000000000000000013013560574021424 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/golang.org/fake.go.linux-amd64.tar.gz0000777000000000000000000000000013013560574032244 2fake.go.linux-386.tar.gzustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/golang.org/dl/0000775000000000000000000000000013013560574022023 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/golang.org/dl/index.html0000664000000000000000000012567113013560574024034 0ustar Downloads - The Go Programming Language

Downloads

After downloading a binary release suitable for your system, please follow the installation instructions.

If you are building from source, follow the source installation instructions.

Stable versions

go1.3.3 ▾

File name Kind OS Arch SHA1 Checksum
go1.3.3.src.tar.gz Source b54b7deb7b7afe9f5d9a3f5dd830c7dede35393a
go1.3.3.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit 04b3e38549183e984f509c07ad40d8bcd577a702
go1.3.3.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit 88f35d3327a84107aac4f2f24cb0883e5fdbe0e5
go1.3.3.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit 49756b700670ae4109e555f2e5f9bedbaa3c50da
go1.3.3.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit a89b570a326e5f8c9509f40be9fa90e54b3bf7a7
go1.3.3.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit dfe68de684f6e8d9c371d01e6d6a522efe3b8942
go1.3.3.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit be686ec7ba68d588735cc2094ccab8bdd651de9e
go1.3.3.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 9aec7e9eff11100a6db026d1b423d1250925e4c4
go1.3.3.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit 6435e50059fe7fa0d60f1b15aab7f255a61816ce
go1.3.3.freebsd-386.tar.gz Archive FreeBSD 32-bit 875a5515dd7d3e5826c7c003bb2450f3129ccbad
go1.3.3.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 8531ae5e745c887f8dad1a3f00ca873cfcace56e
go1.3.3.linux-386.tar.gz Archive Linux 32-bit c26c1bb756f83e63d0dc850c2128367d17b99af09c7e5407e8e7de50e9716d41
go1.3.3.linux-amd64.tar.gz Archive Linux 64-bit c26c1bb756f83e63d0dc850c2128367d17b99af09c7e5407e8e7de50e9716d41
go1.3.3.windows-386.zip Archive Windows 32-bit ba99083b22e0b22b560bb2d28b9b99b405d01b6b
go1.3.3.windows-386.msi Installer Windows 32-bit 6017a0e1667a5a41109f527b405bf6e0c83580f5
go1.3.3.windows-amd64.zip Archive Windows 64-bit 5f0b3b104d3db09edd32ef1d086ba20bafe01ada
go1.3.3.windows-amd64.msi Installer Windows 64-bit 25112a8c4df93dc4009e65eff00bc4ef76f94e46

go1.3.2 ▾

File name Kind OS Arch SHA1 Checksum
go1.3.2.src.tar.gz Source 67d3a692588c259f9fe9dca5b80109e5b99271df
go1.3.2.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit d1652f6e0ed3063b7b43d2bc12981d927bc85deb
go1.3.2.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit d040c85698c749fdbe25e8568c4d71648a5e3a75
go1.3.2.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit d20375615cf8e36e3c9a9b6ddeef16eff7a4ea89
go1.3.2.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit f11930cfb032d39ab445f342742865c93c60ec14
go1.3.2.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit 36ca7e8ac9af12e70b1e01182c7ffc732ff3b876
go1.3.2.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit 323bf8088614d58fee2b4d2cb07d837063d7d77e
go1.3.2.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit e1529241fcef643e5f752c37dc4c86911df91338
go1.3.2.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit fd8637658fcb133423e794c44029ce3476b48e0c
go1.3.2.freebsd-386.tar.gz Archive FreeBSD 32-bit fea3ef264120b5c3b4c50a8929d56f47a8366503
go1.3.2.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 95b633f45156fbbe79076638f854e76b9cd01301
go1.3.2.linux-386.tar.gz Archive Linux 32-bit 3cbfd62d401a6ca70779856fa8ad8c4d6c35c8cc
go1.3.2.linux-amd64.tar.gz Archive Linux 64-bit 0e4b6120eee6d45e2e4374dac4fe7607df4cbe42
go1.3.2.windows-386.zip Archive Windows 32-bit 86160c478436253f51241ac1905577d337577ce0
go1.3.2.windows-386.msi Installer Windows 32-bit 589c35f9ad3506c92aa944130f6a950ce9ee558b
go1.3.2.windows-amd64.zip Archive Windows 64-bit 7f7147484b1bc9e52cf034de816146977d0137f6
go1.3.2.windows-amd64.msi Installer Windows 64-bit a697fff05cbd4a4d902f6c33f7c42588bcc474bc

go1.3.1 ▾

File name Kind OS Arch SHA1 Checksum
go1.3.1.src.tar.gz Source bc296c9c305bacfbd7bff9e1b54f6f66ae421e6e
go1.3.1.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit 84f70a4c83be24cea696654a5b55331ea32f8a3f
go1.3.1.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit 244dfba1f4239b8e2eb9c3abae5ad63fc32c807a
go1.3.1.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit 16e0df7b90d49c8499f71a551af8b595e2faa961
go1.3.1.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit 13296cd9a980819bf2304d7d24a38a1b39719c13
go1.3.1.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit 40716361d352c4b40252e79048e8bc084c3f3d1b
go1.3.1.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit a7271cbdc25173d0f8da66549258ff65cca4bf06
go1.3.1.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 49bf5f14d2683fb99161fcb7025af60ec2d3691f
go1.3.1.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit 5d4728e0b3c3fd9fc657cc192c6b9fb3f837823b
go1.3.1.freebsd-386.tar.gz Archive FreeBSD 32-bit 586debe95542b3b56841f6bd2e5257e301a1ffdc
go1.3.1.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 99e23fdd33860d837912e8647ed2a4b3d2b09d3c
go1.3.1.linux-386.tar.gz Archive Linux 32-bit 36f87ce21cdb4cb8920bb706003d8655b4e1fc81
go1.3.1.linux-amd64.tar.gz Archive Linux 64-bit 3af011cc19b21c7180f2604fd85fbc4ddde97143
go1.3.1.windows-386.zip Archive Windows 32-bit 64f99e40e79e93a622e73d7d55a5b8340f07747f
go1.3.1.windows-386.msi Installer Windows 32-bit df37e307c52fbea02070e23ae0a49cb869d54f33
go1.3.1.windows-amd64.zip Archive Windows 64-bit 4548785cfa3bc228d18d2d06e39f58f0e4e014f1
go1.3.1.windows-amd64.msi Installer Windows 64-bit 88c5d9a51a74c2846226a08681fc28cd3469cba0

go1.3 ▾

File name Kind OS Arch SHA1 Checksum
go1.3.src.tar.gz Source 9f9dfcbcb4fa126b2b66c0830dc733215f2f056e
go1.3.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit 159d2797bee603a80b829c4404c1fb2ee089cc00
go1.3.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit bade975462b5610781f6a9fe8ac13031b3fb7aa6
go1.3.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit 07e7142540558f432a8750eb6cb25d6b06ed80bb
go1.3.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit c908ecdb177c8a20abd61272c260b15e513f6e73
go1.3.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit 82ffcfb7962ca7114a1ee0a96cac51c53061ea05
go1.3.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit 8d768f10cd00e0b152490291d9cd6179a8ccf0a7
go1.3.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 631d6867d7f4b92b314fd87115e1cefadeeac2ab
go1.3.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit 4e8f2cafa23797211fd13f3fa4893ce3d5f084c4
go1.3.freebsd-386.tar.gz Archive FreeBSD 32-bit 8afa9574140cdd5fc97883a06a11af766e7f0203
go1.3.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 71214bafabe2b5f52ee68afce96110031b446f0c
go1.3.linux-386.tar.gz Archive Linux 32-bit 22db33b0c4e242ed18a77b03a60582f8014fd8a6
go1.3.linux-amd64.tar.gz Archive Linux 64-bit b6b154933039987056ac307e20c25fa508a06ba6
go1.3.windows-386.zip Archive Windows 32-bit e4e5279ce7d8cafdf210a522a70677d5b9c7589d
go1.3.windows-386.msi Installer Windows 32-bit d457a86ce6701bb96608e4c33778b8471c48a764
go1.3.windows-amd64.zip Archive Windows 64-bit 1e4888e1494aed7f6934acb5c4a1ffb0e9a022b1
go1.3.windows-amd64.msi Installer Windows 64-bit e81a0e4f551722c7682f912e0485ad20a287f2ef

go1.2.2 ▾

File name Kind OS Arch SHA1 Checksum
go1.2.2.src.tar.gz Source 3ce0ac4db434fc1546fec074841ff40dc48c1167
go1.2.2.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit 360ec6cbfdec9257de029f918a881b9944718d7c
go1.2.2.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit 4219b464e82e7c23d9dc02c193e7a0a28a09af1a
go1.2.2.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit dff27e94c8ff25301cd958b0b1b629e97ea21f03
go1.2.2.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit f1fb44aa22cba3e81dc33f88393a54e49eae0d8b
go1.2.2.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit 24c182718fd61b2621692dcdfc34937a6b5ee369
go1.2.2.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit 19be1eca8fc01b32bb6588a70773b84cdce6bed1
go1.2.2.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 2d4b49f1105a78e1ea31d7f9ea0b43909cc209be
go1.2.2.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit 5d78f2a3fe82b01fe5dfcb267e703e754274b253
go1.2.2.freebsd-386.tar.gz Archive FreeBSD 32-bit d226b8e1c3f75d31fa426df63aa776d7e08cddac
go1.2.2.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 858744ab8ff9661d42940486af63d451853914a0
go1.2.2.linux-386.tar.gz Archive Linux 32-bit d16f892173b0589945d141cefb22adce57e3be9c
go1.2.2.linux-amd64.tar.gz Archive Linux 64-bit 6bd151ca49c435462c8bf019477a6244b958ebb5
go1.2.2.windows-386.zip Archive Windows 32-bit 560bb33ec70ab733f31ff15f1a48fe35963983b9
go1.2.2.windows-386.msi Installer Windows 32-bit 60b91a7bf68596b23978acb109d1ff8668b7d18f
go1.2.2.windows-amd64.zip Archive Windows 64-bit 9ee22fe6c4d98124d582046aab465ab69eaab048
go1.2.2.windows-amd64.msi Installer Windows 64-bit c8f5629bc8d91b161840b4a05a3043c6e5fa310b

Unstable versions

go1.4beta1 ▾

This is an unstable version of Go. Use with caution.

File name Kind OS Arch SHA1 Checksum
go1.4beta1.src.tar.gz Source f2fece0c9f9cdc6e8a85ab56b7f1ffcb57c3e7cd
go1.4beta1.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit a360e7c8f1d528901e721d0cc716461f8a636823
go1.4beta1.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit d863907870e8e79850a7a725b398502afd1163d8
go1.4beta1.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit ee4d1f74c35eddbdc49e9fb01e86a971e1bb54a7
go1.4beta1.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit c118f624262a1720317105d116651f8fb4b80383
go1.4beta1.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit ad8798fe744bb119f0e8eeacf97be89763c5f12a
go1.4beta1.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit e08df216d9761c970e438295129721ec8374654a
go1.4beta1.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 831e95cc381cc1afd6c4bfa886e86790f1c96de6
go1.4beta1.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit dc0b5805ba117654dd95c84ce7872406380de3d5
go1.4beta1.freebsd-386.tar.gz Archive FreeBSD 32-bit 65045b7a5d2a991a45b1e86ad11252bc84043651
go1.4beta1.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 42fbd5336437dde85b34d774bfed111fe579db88
go1.4beta1.linux-386.tar.gz Archive Linux 32-bit 122ea6cae37d9b62c69efa3e21cc228e41006b75
go1.4beta1.linux-amd64.tar.gz Archive Linux 64-bit d2712acdaa4469ce2dc57c112a70900667269ca0
go1.4beta1.windows-386.zip Archive Windows 32-bit a6d75ca59b70226087104b514389e48d49854ed4
go1.4beta1.windows-386.msi Installer Windows 32-bit 1f8d11306d733bec975f2d747b26810926348517
go1.4beta1.windows-amd64.zip Archive Windows 64-bit 386deea0a7c384178aedfe48e4ee2558a8cd43d8
go1.4beta1.windows-amd64.msi Installer Windows 64-bit ec3ec78072128d725878404a5ce27bd1c1e7132b

go1.3rc2 ▾

This is an unstable version of Go. Use with caution.

File name Kind OS Arch SHA1 Checksum
go1.3rc2.src.tar.gz Source 53a5b75c8bb2399c36ed8fe14f64bd2df34ca4d9
go1.3rc2.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit 600433eccda28b91b2afe566142bce759d154b49
go1.3rc2.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit 36fa30bfdeb8560c5d9ae57f02ec0cdb33613cb5
go1.3rc2.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit c41c4e55017d3d835cf66feaaf18eeaeabaa066a
go1.3rc2.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit 4cbdcccac38eed1ebffbbf1eba594724e5d05a77
go1.3rc2.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit 84c25957096d4700f342c10f82f1f720bf646f6e
go1.3rc2.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit 1bd241130b5e7a3eb4876fbb17257b16ea9db67d
go1.3rc2.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 18c8ed409a7ba97a61e00f00982361d7c84f7fdb
go1.3rc2.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit 33d2129c26ea0cb5f147fa5f24395c8ed5c4433f
go1.3rc2.freebsd-386.tar.gz Archive FreeBSD 32-bit 3e5394e0f4eb99c32510dda48eb4dc1af9717a41
go1.3rc2.freebsd-amd64.tar.gz Archive FreeBSD 64-bit bbaba53742cf43d96abca710cf49fe8c0ede6673
go1.3rc2.linux-386.tar.gz Archive Linux 32-bit 7462cb654712ef6785ccae5b75ed393de6f49da2
go1.3rc2.linux-amd64.tar.gz Archive Linux 64-bit 3a7d86a3245b4c8bd4dc5b1ff4e0073c2d1b81b5
go1.3rc2.windows-386.zip Archive Windows 32-bit f3f7a995baf77742b813723bc823d584466cb26f
go1.3rc2.windows-386.msi Installer Windows 32-bit a1138a6f7d22768eac73dfb254a1af8531aaeb1b
go1.3rc2.windows-amd64.zip Archive Windows 64-bit 607b6ed4830785d166d83029a76e6975b2e99068
go1.3rc2.windows-amd64.msi Installer Windows 64-bit dba588d51f9b9353c7bdc271cecea065eea06250

go1.3rc1 ▾

This is an unstable version of Go. Use with caution.

File name Kind OS Arch SHA1 Checksum
go1.3rc1.src.tar.gz Source 6a9dac2e65c07627fe51899e0031e298560b0097
go1.3rc1.darwin-386-osx10.6.tar.gz Archive OS X 10.6+ 32-bit a15031c21871d9ffb567c7d204653b32f0d84737
go1.3rc1.darwin-386-osx10.8.tar.gz Archive OS X 10.8+ 32-bit 7ace88dfe731c38e83cee27f23eb2588419cf249
go1.3rc1.darwin-386-osx10.6.pkg Installer OS X 10.6+ 32-bit 8de0f308c51cec5fcec45fde762967723ef61eb9
go1.3rc1.darwin-386-osx10.8.pkg Installer OS X 10.8+ 32-bit 498e0840c44258e6b29eb5aa34b2fb3c31e79fdd
go1.3rc1.darwin-amd64-osx10.6.tar.gz Archive OS X 10.6+ 64-bit d250f20d84c310aa82053dea16743b223bbf933a
go1.3rc1.darwin-amd64-osx10.8.tar.gz Archive OS X 10.8+ 64-bit e3fb91fcfa2dfa97e451de9048ec5788713bc94e
go1.3rc1.darwin-amd64-osx10.6.pkg Installer OS X 10.6+ 64-bit 02e6537c9a3f0cc80dcf901b40683eeab6d8bebf
go1.3rc1.darwin-amd64-osx10.8.pkg Installer OS X 10.8+ 64-bit 17c42d6e6b5ca99fcd1e6927a79652d7e630a226
go1.3rc1.freebsd-386.tar.gz Archive FreeBSD 32-bit 953a95277ef06da98f0b8d7bb9bd02f4846374ff
go1.3rc1.freebsd-amd64.tar.gz Archive FreeBSD 64-bit 3c0a03ee5a64f6db46298fa3ad26d577ef7b2db5
go1.3rc1.linux-386.tar.gz Archive Linux 32-bit 07c656173c444e4373a799141c1cb28128a345eb
go1.3rc1.linux-amd64.tar.gz Archive Linux 64-bit affaccfd69a694e0aa59466450e4db5260aeb1a3
go1.3rc1.windows-386.zip Archive Windows 32-bit d43c973adede9e8f18118a2924d8b825352db50a
go1.3rc1.windows-386.msi Installer Windows 32-bit 23534cce0db1f8c0cc0cf0f70472df59ac26bbfa
go1.3rc1.windows-amd64.zip Archive Windows 64-bit 312358b64711fd827f9dfb0cef61383f9eb5057b
go1.3rc1.windows-amd64.msi Installer Windows 64-bit d089fbe3c12b8ec8d3e30526b3eb604c9ae84c7d

Older versions

Older releases of Go are available at Google Code.

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/golang.org/fake.go.linux-386.tar.gz0000664000000000000000000000036313013560574025543 0ustar ƶXTһN0`~S U$mj#'}|Bz :r||ߕOXlrd^034V3Tn #@ Ww_KU>ٸ6?q9GV*K/씿5?>߬sgV+ah)I]6_V^urړCS$iO?O{$?(ubuntu-make-16.11.1ubuntu1/tests/data/server-content/sublimetext.com/0000775000000000000000000000000013013560574022511 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/sublimetext.com/3/0000775000000000000000000000000013013560574022653 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/sublimetext.com/3/index.html0000664000000000000000000006357413013560574024667 0ustar Sublime Text - Download

Sublime Text 3

Download

Sublime Text 3 is currently in beta. The latest build is 3103.

Sublime Text may be downloaded and evaluated for free, however a license must be purchased for continued use. There is currently no enforced time limit for the evaluation.

For notification about new versions, follow sublimehq on twitter.

Even more bleeding-edge versions are available in the dev builds.

Sublime Text 2 is also still available.


Build 3103

Release Date: 9 February 2016
  • Added new Syntax Definition file format, .sublime-syntax
  • Added a custom regex engine that matches multiple regexps in parallel, for faster file loading and indexing
  • Improved Unicode support, including combining character rendering, character classification in regex searches, and case insensitivity in Goto Anything matching
  • Packages are now on GitHub
  • Incorporates many community provided improvements to the above packages, with significant improvements to HTML, CSS, JavaScript, Go, D and SQL
  • Added Panel Switcher to status bar
  • Better handling of troublesome files during indexing
  • Improved file change detection
  • Added "Profile Events" to the Command Palette, to help identify slow plugins
  • Build Systems may now define a list of file name wildcard patterns to trigger on, via the file_patterns key
  • prompt_open_file and related commands now accept an initial_directory argument
  • Improved indenting behavior when indent_to_bracket is enabled
  • Spell Checker now reads from manually edited user preferences on the fly
  • Stability improvements for Find in Files when using regular expressions that result in significant backtracking
  • Fixed file truncation when using hexadecimal encoding
  • Fixed brackets in strings influencing auto indent
  • Fixed inconsistencies in Goto Anything when selecting symbols
  • Fixed tab completion regression in 3081, where h1..h6 HTML completions were not triggering
  • Fixed Goto Definition command not working when placed in a submenu
  • OSX: Fixed Emoji & Symbols popup failing to insert text in some cases
  • Windows: Added support for inserting characters from outside of the BMP
  • Windows: ctrl+alt+p is no longer bound by default, due to compatibility issues with some keyboard layouts
  • Windows: Updated code signing certificate to no longer use SHA1
  • Linux: Fixed a file permission issue when running without --wait
  • Linux: crash_reporter is statically linked, improving system compatibility
  • API: Added Window.is_sidebar_visible() and Window.set_sidebar_visible()
  • API: Added View.is_auto_complete_visible()
  • API: Added find_output_panel(), destroy_output_panel(), active_panel() and panels()
  • API: Added create_output_panel() now accepts an optional parameter, "unlisted"

Build 3083

Release Date: 26 March 2015
  • Fixed high CPU usage caused by a corrupt index. This was occuring for some users upgrading from 3065
  • Added setting index_workers to control the number of threads used for file indexing. By default the number of threads is based on the number of CPU cores. By setting index_workers to 1 or 2, indexing will be slower, but less intrusive
  • Fixed a crash when showing the Command Palette with an empty .sublime-build file
  • Tab completion no longer completes numbers. Edit/Show Completions can still be used for this

Build 3080

Release Date: 24 March 2015
  • Fixed Redo sometimes restoring the selection to the incorrect location
  • Reworked how Build Systems are selected (More Information)
  • Build Systems may now declare "keyfiles" (e.g., 'Makefile' for the Make build system) to better auto detect which build system to use
  • Improved handling of build systems that generate lots of output
  • New windows always use the automatic build system, rather than the build system of the last used window
  • Command Palette now remembers the last entered string
  • Improved change detection for files that disappear and reappear, as happens with disconnected network drives
  • atomic_save is disabled by default
  • Right clicking on a URL will show an "Open URL" menu item
  • Added Goto Definition to the context menu
  • Improved behavior of Goto Definition when using multiple panes
  • Misspelled words can now be added to the dictionary, in addition to being ignored
  • Fixed Ignored Words not persisting after exiting
  • Fixed a long standing issue with spell checking and non-ascii characters
  • Added spelling_selector setting, to control what text is checked for misspellings
  • Tweaked handling of syntax definitions and unused captures, resolving an issue with spell checking in Markdown links.
  • Goto Anything supports :line:col syntax in addition to :line
  • Added Edit Project to the Command palette
  • Improved quote auto pairing logic
  • Added <current file> option to Find in Files
  • Improved Console Panel scrolling behavior
  • .tmLanguage files may contain a hidden setting, to indicate they shouldn't be displayed to the user
  • Improved some error messages when parsing .tmLanguage files
  • remember_open_files setting is now defaults to false. Note that this change will have no effect if the hot_exit setting is left at its default value of true
  • Added auto_complete_cycle setting
  • Fixed Minimap refusing to draw on very large windows
  • Fixed not being able to click on the selected row of the auto complete popup
  • Fixed sidebar icons sometimes being invisible on startup
  • Transient sheets (e.g., as created by Goto Anything when previewing files) are no longer added to the Recently Closed list
  • Improved scrolling behavior when line_padding_top is > 0
  • Fixed a bug with scrolling tabs, where a 1 pixel line would occasionally appear underneath them
  • Fixed tabset background being set to the wrong color on startup if different colored tabs are used
  • Updated to a never version of leveldb, fixing constant low level CPU usage if the index becomes corrupted
  • Fixed a crash that could occur when directories are being rapidly deleted and recreated
  • Fixed a crash that occurred when dragging rows scrolled out of view in the side bar
  • Fixed a long standing plugin_host crash triggered via modal dialogs
  • Fixed a typo in the "Save Workspace As" dialog
  • Fixed incorrect menu mnemonics
  • Linux: Added sudo save
  • Windows: Popup windows are able to receive scroll wheel input
  • Windows: subl.exe command line helper accepts wildcards
  • Windows: Fixed access denied errors that could occur when saving with atomic_save disabled
  • Windows: Added workaround for broken std::condition_variable in MSVC 2012, fixing a crash in plugin_host
  • Windows: Added more descriptive errors when the Update Installer fails to rename a folder
  • Windows: Fixed incorrect window sizing after making a maximised window full screen
  • OSX: Added work around for performActionForItemAtIndex: taking an excessively long time in Yosemite. This affected any commands that had a corresponding menu item.
  • OSX: Workaround for an OS issue with zero size windows and OpenGL views
  • OSX: subl command line tool no longer uses Distributed Objects, resolving some intermittent failures
  • Posix: Fixed new files not respecting the umask permission flags
  • API: Added View.show_popup() and related functions
  • API: Added sublime.yes_no_cancel_dialog()
  • API: Added sublime.expand_variables()
  • API: Added Window.extract_variables()
  • API: Added Sheet.view()
  • API: Window.show_quick_panel() now accepts the flag sublime.KEEP_OPEN_ON_FOCUS_LOST
  • API: Window.show_quick_panel() will now scroll to the selected item when shown
  • API: Fixed on_post_window_command() not getting called

Build 3065

Release Date: 27 August 2014
  • Added sidebar icons
  • Added sidebar loading indicators
  • Sidebar remembers which folders are expanded
  • Tweaked window closing behavior when pressing ctrl+w / cmd+w
  • Improved quote auto pairing logic
  • Selected group is now stored in the session
  • Added remember_full_screen setting
  • Fixed a lockup when transitioning from a blinking to a solid caret
  • Fixed a crash in plugin_host
  • Fixed a crash triggered by Goto Anything cloning views
  • Windows: Added command line helper, subl.exe
  • OSX: Added 'New Window' entry to dock menu
  • Posix: Using correct permissions for newly created files and folders
  • API: Updated to Python 3.3.3

Build 3059

Release Date: 17 December 2013
  • Added tab scrolling, controlled by the enable_tab_scrolling setting
  • Added image preview when opening images
  • Encoding and line endings can be displayed in the status bar with the show_encoding and show_line_endings settings
  • Added settings caret_extra_top, caret_extra_bottom and caret_extra_width to control the caret size
  • Added index_exclude_patterns setting to control which files get indexed
  • Automatically closing windows when the last tab is dragged out
  • Changed tab close behavior: the neighboring tab is now always selected
  • When the last file is closed, a new transient file is created automatically
  • Ctrl+Tab ordering is stored in the session
  • Added minimap_scroll_to_clicked_text setting
  • Improved error messages when unable to save files
  • Auto complete now works as expected in macros
  • Minor improvements to Python syntax highlighting
  • Vintage: A block caret is now used
  • Vintage: Improved behavior of visual line mode with word wrapped lines
  • Find in Files will no longer block when FIFOs are encountered
  • Linux: Added menu hiding
  • Linux: Fixed incorrect handling of double clicks in the Find panel
  • Linux: Fixed incorrect underscore display in some menus
  • Posix: Fixed new files being created with unexpected permissions
  • Windows: SSE support is no longer required for 32 bit builds
  • API: Window.open_file now accepts an optional group parameter
  • API: Plugins may now call Settings.clear_on_change() within a callback from Settings.add_on_change()
  • API: Calling Settings.add_on_change() from within a settings change callback won't cause the added callback to be run

Build 3047

Release Date: 27 June 2013
  • Beta is now open to non-registered users
  • Windows and Linux: Added High DPI support
  • Improved file change detection
  • Improved rendering performance
  • HTML tag auto completion is better behaved in script tags
  • Fixed a crash on exit that could occur when hot_exit is disabled
  • Linux and OSX: atomic_save is adaptively disabled when it's not possible to preserve file permissions
  • OSX: Fixed context menus not working when the application is in the background
  • Windows: Auto updater supports updating from unicode paths
  • API: Plugins in zip files are able to be overridden via files on disk
  • API: Added support for the termios module on Linux and OS X
  • API: Fixed Selection.contains
  • API: Fixed settings objects getting invalidated too early with cloned views

Build 3033

Release Date: 7 May 2013
  • New auto update system for Windows and OS X
  • Previewing a file from the side bar will no longer add an entry to the OPEN FILES section of the side bar
  • Added Paste from History
  • Added setting 'auto_find_in_selection', for S2 style Find in Selection logic
  • Find panel has a drop down arrow to select previous items
  • Pressing right in the Goto Anything overlay will open the selected file without closing the overlay
  • Fixed several crash bugs
  • Further startup time improvements
  • Improved HTML completions when typing outside of tags
  • Fixed Close Tag not respecting self closing tags
  • PHP: Improved auto indenting for the alternative control syntax
  • Added setting always_prompt_for_file_reload
  • Improved handling of deleted files when restoring sessions
  • Deleting a file via the side bar will first close the corresponding view, if any
  • "Remove all Folders from Project" now prompts to confirm
  • Added telemetry. Telemetry is disabled by default, but can be turned on with the enable_telemetry setting
  • Using Google Breakpad to automatically report crashes
  • Updated syntax highlighting for PHP, Haskell and Pascal
  • Symlinks are followed by default in folders added to the side bar
  • Windows: Fixed erroneous entries in system menu
  • Windows: New style Open Folder dialogs are used on Vista and later
  • API: Significantly improved communication speed with plugin_host
  • API: Added view.close()
  • API: Added view.show_popup_menu()
  • API: Added is_valid() method to view and window, to determine if the handle has been invalidated
  • API: Added on_post_text_command and on_post_window_command
  • API: on_text_command and on_window command are now called when the menu is used
  • API: Added sublime.get_macro()
  • API: view.substr(point) now has the same semantics as S2 for out of bounds addresses
  • API: view.command_history(0, True) now returns the last modifying command, as expected

Build 3021

Release Date: 14 March 2013
  • Linux: Fixed atomic_save working incorrectly with symlinks
  • Windows: Fixed a crash under Windows 7 x64
  • Fixed a crash that could occur on file open

Build 3019

Release Date: 12 March 2013
  • Added Jump Back and Jump Forward commands, available from the Goto menu
  • HTML: Improved completions and auto indent
  • HTML: Tags are closed when </ is entered. This is controlled by the auto_close_tags setting
  • Smarter word navigation
  • File saves are atomic. This can be disabled with the atomic_save setting
  • Find and Replace panels automatically resize when multi line strings are entered
  • Faster loading of large, plain text files
  • Improved console scrolling performance on high resolution displays
  • Improved handling of files with extremely long lines
  • Minimap view rectangle auto hides (controlled by the always_show_minimap_viewport setting)
  • Indexing: Added detection of stuck workers
  • Updated C# package
  • Added invert_selection command
  • CSS: Completions will not be offered when typing in selectors
  • Fixed Reveal in Side Bar
  • Fixed C++ syntax highlighting for nested class forward declarations
  • Exec panel scrolls again
  • OSX: Added support for line numbers sent via apple events
  • Windows: ok_cancel_dialog uses new visual styles
  • Linux: Using the correct version number for the deb files
  • API: Added on_text_command() and on_window_command()
  • API: Added load_resource(), load_binary_resource() and find_resources()
  • API: Added encode_value() and decode_value()
  • API: view.sel() supports negative indices
  • API: Implemented settings.add_on_change() and settings.clear_on_change()
  • API: view.add_regions() will accept package relative paths for the icon
  • API: view.add_regions() can show underlines
  • API: Added on_pre_close() callback
  • API: view.window() will now work even if the view isn't frontmost

Build 3012

Release Date: 10 February 2013
  • Fixed a syntax highlighting regression in 3011

Build 3011

Release Date: 9 February 2013
  • Improved protection against degenerate syntax definitions
  • Linux: Fixed version incompatibilities with libffi
  • OSX: Fixed exec command on 10.7
  • OSX: Fixed incompatibility between Dictionary lookup and gpu_window_buffer
  • Objective-C: Improved symbol indexing
  • API: Plugins may import modules from plugin_loaded()
  • API: sublime.version(), sublime.platform(), sublime.architecture(), and sublime.channel() may now be used before plugin_loaded() is called
  • API: Added view.command_history()

Build 3010

Release Date: 3 February 2013
  • OSX: Buttery smooth scrolling on Retina displays
  • Symbol Indexing: fixed degenerate behavior that could cause an explosion in the number of worker processes
  • Symbol Indexing: less worker processes are used, to be more unobtrusive
  • Symbol Indexing: better handling of binary files
  • OSX: Control+C will cancel the current build
  • API: view.insert() returns the number of characters inserted

Build 3009

Release Date: 1 February 2013
  • Improved symbol indexing for Ruby
  • OSX: Reduced CPU usage when gpu_window_buffer is enabled
  • Symbol Indexing works on Windows XP
  • Can monitor indexing behavior by entering sublime.log_indexing(True) in the console
  • Tweaked brace matching logic
  • Removed undesirable animation during startup
  • API: Added _ssl module on OS X and Windows
  • API: Fixed ctypes regression in 3008 on OS X
  • API: Plugins can define plugin_loaded() and plugin_unloaded() module functions. plugin_loaded() will be called when the API is ready to use.
  • API: Added view.find_by_class()
  • API: Added view.expand_by_class()
  • API: Fixed on_new_async()
  • API: Tweaking handling of show_quick_panel when items is a mixed list of strings and sequences

Build 3008

Release Date: 30 January 2013
  • Fixed Open all with current extension as
  • Fixed the Tools/Macros menu
  • Linux: Restored compatibility with older glibc versions
  • Linux: Added Installed-Size field to the .deb
  • API: urllib.request can be imported on OS X
  • API: Fixed missing _socket module on 32 bit Windows

Build 3007

Release Date: 30 January 2013
  • OSX: Fixed extraneous dock icons
  • Added Symbol Indexing support for Scala
  • Fixed crash that could occur when using Goto Anything
  • Fixed the ignored_packages setting not working correctly with zipped packages
  • Vintage: Fixed 'o' and 'O'
  • API: Fixed on_query_completions not working correctly in some circumstance
  • API: Re-added view.score_selector
  • API: Selection.add() no longer ignores the xpos

Build 3006

Release Date: 29 January 2013
  • Added Goto Definition, and Goto Symbol in Project
  • Significantly improved startup time
  • Significantly improved Replace All performance
  • Improved matching algorithm used for Goto Anything and Autocomplete, now accepts transposed characters
  • UI: Enhanced pane management
  • UI: Previewing files from the sidebar creates a preview tab
  • UI: Improved animation in the side bar
  • Projects: Multiple workspaces can be created for a single project
  • Projects: When adding folders to the sidebar, symlinks are not followed by default. This can be changed by enabling follow_symlinks in the project.
  • Build Systems: Added 'shell_cmd', which supersedes 'cmd', with more intuitive syntax
  • Build Systems: Better PATH handling behavior on OS X when using shell_cmd.
  • Build Systems: 'Make' build system has an improved error message regex
  • Build Systems: Syntax file can be specified for the output
  • Build Systems: Word wrap is enabled by default
  • Find in Files: Improved handling of binary files
  • Find in Files: Line numbers are hidden in the output
  • Find: Find in Selection will no longer be automatically selected
  • Find: Removed Reverse option
  • OSX: Improved performance on Retina displays
  • OSX: 10.7 or later is required
  • OSX: 64 bit only
  • OSX: System version of Python is no longer a dependency
  • OSX: Italic fonts are synthesized when not available in the typeface
  • Linux: .deb files are provided
  • Linux: Starting from the command line will daemonize the process by default
  • API: Upgraded from Python 2.6 to Python 3.3
  • API: Plugins run out-of-process
  • API: Plugin API is now threadsafe
  • API: Some API events are now run asynchronously
  • API: begin_edit() / end_edit() are no longer accessible
  • API: Projects are exposed to the API
  • API: Added window.settings() and window.template_settings()
  • API: show_quick_panel accepts an on_highlighted callback
ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/0000775000000000000000000000000013013560574021754 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/0000775000000000000000000000000013013560574024125 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/0000775000000000000000000000000013013560574024460 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/0000775000000000000000000000000013013560574026267 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/0000775000000000000000000000000013013560574027020 5ustar ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/final/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/fina0000775000000000000000000000000013013560574027656 5ustar ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/final/js/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/fina0000775000000000000000000000000013013560574027656 5ustar ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/final/js/files.jsubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/images_www/v6/download/8.0.42/fina0000664000000000000000000002136613013560574027670 0ustar add_file("bundles/netbeans-8.2-cpp-linux-x64.sh", 119728128, "d6a89152b36be513c50764fcbfdd975076727f8333b46d1e60798c9fb79196e5", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-cpp-linux-x86.sh", 121939968, "5e152971e57af1a94a4888217de4b59b0a2729a19b7a557dcb36e691c6bfa9bc", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-cpp-macosx.dmg", 153729000, "e1719f1232e390c1d1fdf491b68c2a68c5d9512b38cb65d9f2614dc72af90717", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-cpp-windows-x64.exe", 114888454, "b592275910f3e18282453898fec620d662f9da8049f91796b7ccbd1e90a861ef", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-cpp-windows-x86.exe", 111157666, "d67b74d45eeaf51a46333eaba9550edf567d219c661c9de783eb5ff4b29dddf5", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-html-linux-x64.sh", 121545728, "64a13be8951528d580ceb6409562cf5fed26fadb941c0bd21f7d79ac8ee65b93", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-html-linux-x86.sh", 123757568, "7f937001f0322baafde0f9f3de428d88379953b1d602d63320592a5f89d6f70b", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-html-macosx.dmg", 148854864, "084c34512db43a9027c0ee24bb1dc72364fc64ff6fa1b5ddeface07ba1c80c3b", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-html-windows-x64.exe", 116706475, "1aacd9f89beae4fe2974987d09e278145217b9de56ff2cec21e2dded82e632e3", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-html-windows-x86.exe", 112975690, "917251eac8ecf88ced1398c2643417405726a82b6a9d2c740c60e2063f4853a8", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-javaee-linux.sh", 205376512, "dfde5356d1238bda033b2c2e0035bba763094b8f041fc21320ab5a1fcd61a723", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-javaee-macosx.dmg", 253383489, "5b897c3f1fa657749d5dcddbc3a95a1a15ec35e7cab08aad34befadd7ec3f1e7", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-javaee-windows.exe", 205734991, "8a9a955334767035f81c1ec98204d3c35e3a84d60fa99ee194e22bad24269048", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-javase-linux.sh", 98264064, "075b4ba5e89ac81c0c38c977d53ee47e6ac8614680799465eb3de11128aa347b", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-javase-macosx.dmg", 121538422, "91652f03d8abba0ae9d76a612ed909c9f82e4f138cbd510f5d3679280323011b", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-javase-windows.exe", 98621786, "7b0646306a7488e617837da1517a86c08b7cf6fbe4dd9d74e8a4564b5ffde004", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-linux.sh", 223882240, "0442d4eaae5334f91070438512b2e8abf98fc84f07a9352afbc2c4ad437d306c", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-macosx.dmg", 289710450, "ddcf37e91d960cca6b6a37c95eabf2c6f15330ed708bfd79be796de00da20e5e", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-php-linux-x64.sh", 121545728, "64a13be8951528d580ceb6409562cf5fed26fadb941c0bd21f7d79ac8ee65b93", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-php-linux-x86.sh", 123757568, "7f937001f0322baafde0f9f3de428d88379953b1d602d63320592a5f89d6f70b", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-php-macosx.dmg", 148854864, "084c34512db43a9027c0ee24bb1dc72364fc64ff6fa1b5ddeface07ba1c80c3b", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-php-windows-x64.exe", 116706475, "1aacd9f89beae4fe2974987d09e278145217b9de56ff2cec21e2dded82e632e3", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-php-windows-x86.exe", 112975690, "917251eac8ecf88ced1398c2643417405726a82b6a9d2c740c60e2063f4853a8", "en,ja,zh_CN,pt_BR,ru"); add_file("bundles/netbeans-8.2-windows.exe", 230877002, "c6df4acafb3b8583ec76a643b5df086583ad0bec86072166bc94c65c8731d837", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/hg-l10n-201609300101.zip", 421798, "0fb92b106e4f00f9565e7808364645be293808be2d6d9e2c9687665dda6b9119", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/ide-l10n-201609300101.zip", 24858545, "c77f7aa8ec8fbeb74e31182fde96656bfc4c91a11d25828795ee9528aba3f1b1", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-cpp.zip", 133372879, "7fbff2e15e973315187cf14537ba4915d38ce24e22bcd4317fd5b296c1d46c64", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-html.zip", 128805612, "51ae034b99f16c3bab66ab7dfd07c3554953e78828c2493cde1bb67c95c43e2b", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-javaee.zip", 296813596, "5f44f36c6f0c5ae2b322994024bc4beba4c22a9eccbb22e878d5b1151fca15fb", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-javase.zip", 195793312, "cf6f94517faa5dbedede4b8a7a6e6d5a65ca931eeae3809245ba7321bf539aea", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-php.zip", 128805612, "51ae034b99f16c3bab66ab7dfd07c3554953e78828c2493cde1bb67c95c43e2b", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-platform-src.zip", 29983317, "49fb4bc39677fff93994bded90d702447f89f92b402c80a59073bece69a0b270", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101-src.zip", 217356974, "5a7141176fe655807f04bdde12073116a77c1844e4ca7a071d95930b7cd7d5ac", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/netbeans-8.2-201609300101.zip", 351110790, "ad9888334b9a6c1f1138dcb2eccc8ce4921463e871e46def4ecc617538160948", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/stableuc-l10n-201609300101.zip", 7355658, "2ea41b2d226746f3805b98c5d73a8a6d6e7d6f3ddc2f10800ab8eb2e863cc91c", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/testdist-201609300101.zip", 124768148, "27db3792d39b63ced70c3b3822804e805b66bd37611ce7879c9e41ddfb2feae5", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-all-in-one.zip", 343724442, "6de9d9afed88e753265b2dc8a7d73bf0874b5a4b8c710e7f2e592b9a99c7e36a", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-apisupport.zip", 2896220, "eb5e0c7858a56083f404e809dd5964d3db5f749d9cf4d1da17b5ad7f3a62a558", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-cndext.zip", 139909, "6860d4fd8b33fe6cdfbf2b8a2bfb8362a4e828e7ab29d0c2eb16a226305190b3", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-cnd.zip", 20397918, "bfc9a08c380d93547e0547cbf4a828ad8017633661b6ca207a456d790af933c1", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-dlight.zip", 5509292, "7529c5769487bd2d8a32cd3d2882b7b0e3d666908c13c92325b3c483aa9630df", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-enterprise.zip", 90801148, "b485d48003c546660204cff7a73951ee707166f0c4b1a237ce2bd19bbd29db94", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-ergonomics.zip", 2812243, "912285818587f017da70ef5a9ba8de05aeab103c653fa5d5a2377ada579c4a55", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-extide.zip", 2754317, "7788e9e7856cf2319a2e4d268fc9e4150088529bfddb3fafd024b76fe284bc01", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-groovy.zip", 7455645, "ae984fa6aa1d68825caf96b1f2fa8829a1f4c08b0bf5ffdae290e4536c91d7f3", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-harness.zip", 6524065, "b7c41108676257ac43c86c03c822f90f453ce1be3073eb6a99cfd8394e71a5ad", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-ide.zip", 80612796, "cfadcba85779ba7421620abb92ec3d7d2076bedbd50331298dbfaf54f0ddc295", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-javacard.zip", 9321532, "0ceb83a3a1d8c6ba1fb599c9bc4fdf43a5c6bcf8fad0e354edd536f4c0e64bc6", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-java.zip", 76912931, "4e0865c3e503e60b0f52112e28e7189f12fcaf0665768b71a98e4f5274caf8c0", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-mobility.zip", 2058726, "ecdf6c3d6c906df52f93c64901f436bb28416bf9bf746e76bfc9ca67179fc9c4", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-nb-etc.zip", 1991308, "27550ce9074b6f31c4c742b3caf57e6fb70c472f64f7ec67cf6e5d33995d4430", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-php.zip", 6737747, "ba049df89a66c9af87b3ecaa5d208f6b8cab41de81c503ebc575b1a339f67f4c", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-platform.zip", 18792546, "606904ba6319e973532ac0933b4e1f18b08a56ce6d641f5e3b4cf67c5418c666", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-profiler.zip", 5262093, "0e19d5a69d645d7f19d88dfa4cf50e92161bcfec74e7ec95168ee3c84153adc4", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-webcommon.zip", 11308378, "42311440906b5019f919e70182fc87c633cd4b441759b2fd7a9a22904f963cf5", "en,ja,zh_CN,pt_BR,ru"); add_file("zip/moduleclusters/netbeans-8.2-201609300101-websvccommon.zip", 621938, "798ad280d2dea48fb0b6b07c0a637c4e3250d410d4ee711f9175d37bc297198b", "en,ja,zh_CN,pt_BR,ru"); ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/downloads/0000775000000000000000000000000013013560574023746 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/netbeans.org/downloads/zip.html0000664000000000000000000003363613013560574025451 0ustar
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
ubuntu-make-16.11.1ubuntu1/tests/data/server-content/localhost/0000775000000000000000000000000013013560574021357 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/localhost/base-framework-fake64.tgz0000664000000000000000000000063313013560574026072 0ustar yLVr0=C=X7!yOHOuk>+^â%F` * v+i{EkZ b هtr0:{OM?u+MG @~ Jq$aa@ltռ(WӪ(v[GͿ5~H&{ޯ_;:ǝIqL{qw>{Qs7 Cq}+wZ7kan_0 sK_ ubuntu-make-16.11.1ubuntu1/tests/data/server-content/localhost/base-framework-fake32.tgz0000664000000000000000000000063413013560574026066 0ustar 'zLVr0=C=X7! Download Android Studio and SDK Tools | Android Developers
 

Android Studio

The official Android IDE

  • Android Studio IDE
  • Android SDK tools
  • Android 5.0 (Lollipop) Platform
  • Android 5.0 emulator system image with Google APIs
Download Android Studio

To get Android Studio or stand-alone SDK tools, visit developer.android.com/sdk/

Intelligent code editor

At the core of Android Studio is an intelligent code editor capable of advanced code completion, refactoring, and code analysis.

The powerful code editor helps you be a more productive Android app developer.

Code templates and GitHub integration

New project wizards make it easier than ever to start a new project.

Start projects using template code for patterns such as navigation drawer and view pagers, and even import Google code samples from GitHub.

Multi-screen app development

Build apps for Android phones, tablets, Android Wear, Android TV, Android Auto and Google Glass.

With the new Android Project View and module support in Android Studio, it's easier to manage app projects and resources.

Virtual devices for all shapes and sizes

Android Studio comes pre-configured with an optimized emulator image.

The updated and streamlined Virtual Device Manager provides pre-defined device profiles for common Android devices.

Android builds evolved, with Gradle

Create multiple APKs for your Android app with different features using the same project.

Manage app dependencies with Maven.

Build APKs from Android Studio or the command line.

More about Android Studio

Download Android Studio
  • Built on IntelliJ IDEA Community Edition, the popular Java IDE by JetBrains.
  • Flexible Gradle-based build system.
  • Build variants and multiple APK generation.
  • Expanded template support for Google Services and various device types.
  • Rich layout editor with support for theme editing.
  • Lint tools to catch performance, usability, version compatibility, and other problems.
  • ProGuard and app-signing capabilities.
  • Built-in support for Google Cloud Platform, making it easy to integrate Google Cloud Messaging and App Engine.

For more details about features available in Android Studio, read the guide to Android Studio Basics.

If you have been using Eclipse with ADT, be aware that Android Studio is now the official IDE for Android, so you should migrate to Android Studio to receive all the latest IDE updates. For help moving projects, see Migrating to Android Studio.

System Requirements

Windows

  • Microsoft® Windows® 8/7/Vista/2003 (32 or 64-bit)
  • 2 GB RAM minimum, 4 GB RAM recommended
  • 400 MB hard disk space + at least 1 G for Android SDK, emulator system images, and caches
  • 1280 x 800 minimum screen resolution
  • Java Development Kit (JDK) 7
  • Optional for accelerated emulator: Intel® processor with support for Intel® VT-x, Intel® EM64T (Intel® 64), and Execute Disable (XD) Bit functionality

Mac OS X

  • Mac® OS X® 10.8.5 or higher, up to 10.9 (Mavericks)
  • 2 GB RAM minimum, 4 GB RAM recommended
  • 400 MB hard disk space
  • At least 1 GB for Android SDK, emulator system images, and caches
  • 1280 x 800 minimum screen resolution
  • Java Runtime Environment (JRE) 6
  • Java Development Kit (JDK) 7
  • Optional for accelerated emulator: Intel® processor with support for Intel® VT-x, Intel® EM64T (Intel® 64), and Execute Disable (XD) Bit functionality

On Mac OS, run Android Studio with Java Runtime Environment (JRE) 6 for optimized font rendering. You can then configure your project to use Java Development Kit (JDK) 6 or JDK 7.

Linux

  • GNOME or KDE desktop
  • GNU C Library (glibc) 2.11 or later
  • 2 GB RAM minimum, 4 GB RAM recommended
  • 400 MB hard disk space
  • At least 1 GB for Android SDK, emulator system images, and caches
  • 1280 x 800 minimum screen resolution
  • Oracle® Java Development Kit (JDK) 7

Tested on Ubuntu® 12.04, Precise Pangolin (64-bit distribution capable of running 32-bit applications.

Other Download Options

SDK Tools Only

If you prefer to use a different IDE or run the tools from the command line or with build scripts, you can instead download the stand-alone Android SDK Tools. These packages provide the basic SDK tools for app development, without an IDE. Also see the SDK tools release notes.

Platform Package Size SHA-1 Checksum
Windows installer_r24.0.1-windows.exe (Recommended) 92180986 bytes 505d7a95647bccc194b7aa707854422d9c7288d5
android-sdk_r24.0.1-windows.zip 140743633 bytes cc49974e8bfcc865ffe0d887e9a74cf52085c632
Mac OS X android-sdk_r24.0.1-macosx.zip 88535741 bytes 7097c09c72645d7ad33c81a37b1a1363a9df2a54
Linux android-sdk_r24.0.1-linux.tgz 141304203 bytes bc1ccd6b05beb06f59a2011c5a7f2bbab8e87f02

All Android Studio Packages

Select a specific Android Studio package for your platform. Also see the Android Studio release notes.

Platform Package Size SHA-1 Checksum
Windows android-studio-bundle-135.1641136.exe
(Recommended)
868344232 bytes 1931dbaeadb52f5e0a8ba6e2ae60d9df20b2076b
android-studio-ide-135.1641136.exe
(No SDK tools included)
260272840 bytes 464d1c5497ab3d1bdef441365791ab36c89cd5ae
android-studio-ide-135.1641136-windows.zip 246249059 bytes 6d6856aca83f6ff747ca40b10f70edfbbcccd91c
Mac OS X android-studio-ide-1641136.dmg 245729073 bytes 49506ba2cf6b56be4f7d07e6a00c4ec3ba2249d5
Linux android-studio-ide-135.1641136-linux.zip 243917559 bytes 4a582c6e35700f00332783b0b83783f73499aa60
Linux android-studio-ide-135.1641136-linux.zip 243917559 bytes 4f64664ebe496cc6d54f417f25a1707f156d74d2
ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.dartlang.org/0000775000000000000000000000000013013560574022521 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/api.dartlang.org/index.html0000664000000000000000000003474613013560574024534 0ustar Dart SDK - Dart API docs

 
Dart SDK

Welcome to the Dart API reference documentation, covering the official Dart API libraries. Some of the most fundamental Dart libraries include:

  • dart:core: Core functionality such as strings, numbers, collections, errors, dates, and URIs.
  • dart:html: DOM manipulation for web apps.
  • dart:io: I/O for command-line apps.

Except for dart:core, you must import a library before you can use it. Here's an example of importing dart:html and dart:math:

import 'dart:html';
import 'dart:math';

You can install more libraries using the pub package manager. For information on finding, using, and publishing libraries with pub, see pub.dartlang.org.

The main site for learning and using Dart is www.dartlang.org. Check out these additional pages:

This API reference is automatically generated from the source code in the Dart project. If you'd like to contribute to this documentation, see Contributing.

Libraries

dart:async

Support for asynchronous programming, with classes such as Future and Stream.

dart:collection

Classes and utilities that supplement the collection support in dart:core.

dart:convert

Encoders and decoders for converting between different data representations, including JSON and UTF-8.

dart:core

Built-in types, collections, and other core functionality for every Dart program.

dart:developer

Interact with developer tools such as the debugger and inspector.

dart:html

HTML elements and other resources for web-based applications that need to interact with the browser and the DOM (Document Object Model).

dart:indexed_db

A client-side key-value store with support for indexes.

dart:io

File, socket, HTTP, and other I/O support for server applications.

dart:isolate

Concurrent programming using isolates: independent workers that are similar to threads but don't share memory, communicating only via messages.

dart:js

Support for interoperating with JavaScript.

dart:math

Mathematical constants and functions, plus a random number generator.

dart:mirrors

Basic reflection in Dart, with support for introspection and dynamic invocation.

dart:profiler

Please see 'dart:developer'.

dart:svg

Scalable Vector Graphics: Two-dimensional vector graphics with support for events and animation.

dart:typed_data

Lists that efficiently handle fixed sized data (for example, unsigned 8 byte integers) and SIMD numeric types.

dart:web_audio

High-fidelity audio programming in the browser.

dart:web_gl

3D programming in the browser.

dart:web_sql

An API for storing data in the browser that can be queried with SQL.

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.scala-lang.org/0000775000000000000000000000000013013560574023002 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.scala-lang.org/download/0000775000000000000000000000000013013560574024611 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.scala-lang.org/download/index.html0000664000000000000000000003460613013560574026617 0ustar Download | The Scala Programming Language

Download

Choose one of three ways to get started with Scala!
1

Download Scala 2.11.7 binaries for your system (All downloads).

Need help installing?

~ or ~
2

Get started with Typesafe Activator
Typesafe Activator is a browser-based or command-line
tool that helps developers get started with Scala.

~ or ~

Release Notes

For important changes, please consult the release notes.

Software Requirements

The Scala software distribution can be installed on any platform with a Java runtime, version 1.6 or later.

Additional information

You can find the links to prior versions or the latest development version below. To see a detailed list of changes for each version of Scala please refer to the changelog. Note that the different major releases of Scala (e.g. Scala 2.9.3 and Scala 2.10.1) are not binary compatible.

License

The Scala distribution is released under the 3-clause BSD license.
ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.scala-lang.org/fake-scala.tgz0000664000000000000000000000037413013560574025523 0ustar :UN0UOI[(=,{C7A t,&C\ZZJ6qmME֚SmܤIN4ؓ]}?5|_4w'\ç8_ez?,c+gbPq^tKJrI"IU4MwՂ|UbSu$5=w}s'_jO53N+/4.(ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/0000775000000000000000000000000013013560574023740 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/0000775000000000000000000000000013013560574026311 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/0000775000000000000000000000000013013560574030104 5ustar ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/stable/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/st0000775000000000000000000000000013013560574030453 5ustar ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/stable/release/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/st0000775000000000000000000000000013013560574030453 5ustar ././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/stable/release/1.12.1/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/st0000775000000000000000000000000013013560574030453 5ustar ././@LongLink0000644000000000000000000000017500000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/stable/release/1.12.1/sdk/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/st0000775000000000000000000000000013013560574030453 5ustar ././@LongLink0000644000000000000000000000023300000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/stable/release/1.12.1/sdk/dartsdk-linux-ia32-release.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/st0000777000000000000000000000000013013560574034404 2dartsdk-linux-x64.zipustar ././@LongLink0000644000000000000000000000023200000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/stable/release/1.12.1/sdk/dartsdk-linux-x64-release.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/storage.googleapis.com/dart-archive/channels/st0000664000000000000000000000051013013560574030451 0ustar PKuF dart-sdk/PKuF dart-sdk/bin/PK uFdart-sdk/bin/dartPK?uF Adart-sdk/PK?uF A'dart-sdk/bin/PK? uF Rdart-sdk/bin/dartPKubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/0000775000000000000000000000000013013560574022447 5ustar ././@LongLink0000644000000000000000000000017600000000000011607 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/?product=firefox-aurora-latest-ssl&os=linux64&lang=en-USubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/?product=firefox-aurora-latest-0000777000000000000000000000000013013560574042666 2?product=firefox-aurora-latest-ssl&os=linux&lang=en-USustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/en-US/0000775000000000000000000000000013013560574023376 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/en-US/firefox/0000775000000000000000000000000013013560574025040 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/en-US/firefox/developer/0000775000000000000000000000000013013560574027025 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/en-US/firefox/developer/all0000664000000000000000000042023613013560574027527 0ustar Mozilla Firefox Web Browser — Download Developer Edition in your language — Mozilla
Mozilla

Firefox Developer Edition

Download Developer Edition in your language

Download Firefox Developer Edition in your language to experience the newest features and innovations in an unstable environment even before they go to Beta. Give us feedback that will determine what makes it to Final Release and help shape the future of Firefox.

Check the system requirements
Release notes

Fully localized versions

Language Windows Windows 64-bit Mac OS X Linux Linux 64-bit
Acholi Acholi Download Download Download Download Download
Afrikaans Afrikaans Download Download Download Download Download
Albanian Shqip Download Download Download Download Download
Arabic عربي Download Download Download Download Download
Aragonese aragonés Download Download Download Download Download
Armenian Հայերեն Download Download Download Download Download
Assamese অসমীয়া Download Download Download Download Download
Asturian Asturianu Download Download Download Download Download
Azerbaijani Azərbaycanca Download Download Download Download Download
Basque Euskara Download Download Download Download Download
Belarusian Беларуская Download Download Download Download Download
Bengali (Bangladesh) বাংলা (বাংলাদেশ) Download Download Download Download Download
Bengali (India) বাংলা (ভারত) Download Download Download Download Download
Bodo बर' Download Download Download Download Download
Bosnian Bosanski Download Download Download Download Download
Breton Brezhoneg Download Download Download Download Download
Bulgarian Български Download Download Download Download Download
Burmese မြန်မာဘာသာ Download Download Download Download Download
Catalan Català Download Download Download Download Download
Chinese (Simplified) 中文 (简体) Download Download Download Download Download
Chinese (Traditional) 正體中文 (繁體) Download Download Download Download Download
Croatian Hrvatski Download Download Download Download Download
Czech Čeština Download Download Download Download Download
Danish Dansk Download Download Download Download Download
Dutch Nederlands Download Download Download Download Download
English (British) English (British) Download Download Download Download Download
English (South African) English (South African) Download Download Download Download Download
English (US) English (US) Download Download Download Download Download
Esperanto Esperanto Download Download Download Download Download
Estonian Eesti keel Download Download Download Download Download
Finnish suomi Download Download Download Download Download
French Français Download Download Download Download Download
Frisian Frysk Download Download Download Download Download
Fulah Pulaar-Fulfulde Download Download Download Download Download
Gaelic (Scotland) Gàidhlig Download Download Download Download Download
Galician Galego Download Download Download Download Download
German Deutsch Download Download Download Download Download
Greek Ελληνικά Download Download Download Download Download
Gujarati (India) ગુજરાતી (ભારત) Download Download Download Download Download
Hebrew עברית Download Download Download Download Download
Hindi (India) हिन्दी (भारत) Download Download Download Download Download
Hungarian magyar Download Download Download Download Download
Icelandic íslenska Download Download Download Download Download
Indonesian Bahasa Indonesia Download Download Download Download Download
Irish Gaeilge Download Download Download Download Download
Italian Italiano Download Download Download Download Download
Japanese 日本語 Download Download Download Download Download
Kannada ಕನ್ನಡ Download Download Download Download Download
Kashmiri كشمیری Download Download Download Download Download
Kazakh Қазақ Download Download Download Download Download
Khmer ខ្មែរ Download Download Download Download Download
Konkani कोंकनी Download Download Download Download Download
Korean 한국어 Download Download Download Download Download
Latvian Latviešu Download Download Download Download Download
Ligurian Ligure Download Download Download Download Download
Lithuanian lietuvių kalba Download Download Download Download Download
Lower Sorbian Dolnoserbšćina Download Download Download Download Download
Macedonian Македонски Download Download Download Download Download
Maithili मैथिली মৈথিলী Download Download Download Download Download
Malay Melayu Download Download Download Download Download
Malayalam മലയാളം Download Download Download Download Download
Marathi मराठी Download Download Download Download Download
Norwegian (Bokmål) Norsk bokmål Download Download Download Download Download
Norwegian (Nynorsk) Norsk nynorsk Download Download Download Download Download
Occitan (Lengadocian) occitan (lengadocian) Download Download Download Download Download
Oriya ଓଡ଼ିଆ Download Download Download Download Download
Persian فارسی Download Download Download Download Download
Polish Polski Download Download Download Download Download
Portuguese (Brazilian) Português (do Brasil) Download Download Download Download Download
Portuguese (Portugal) Português (Europeu) Download Download Download Download Download
Punjabi (India) ਪੰਜਾਬੀ (ਭਾਰਤ) Download Download Download Download Download
Romanian română Download Download Download Download Download
Romansh rumantsch Download Download Download Download Download
Russian Русский Download Download Download Download Download
Santali संताली Download Download Download Download Download
Serbian Српски Download Download Download Download Download
Sinhala සිංහල Download Download Download Download Download
Slovak slovenčina Download Download Download Download Download
Slovenian Slovenščina Download Download Download Download Download
Songhai Soŋay Download Download Download Download Download
Spanish (Argentina) Español (de Argentina) Download Download Download Download Download
Spanish (Chile) Español (de Chile) Download Download Download Download Download
Spanish (Mexico) Español (de México) Download Download Download Download Download
Spanish (Spain) Español (de España) Download Download Download Download Download
Swedish Svenska Download Download Download Download Download
Tamil தமிழ் Download Download Download Download Download
Telugu తెలుగు Download Download Download Download Download
Thai ไทย Download Download Download Download Download
Turkish Türkçe Download Download Download Download Download
Ukrainian Українська Download Download Download Download Download
Upper Sorbian Hornjoserbsce Download Download Download Download Download
Uzbek Oʻzbek tili Download Download Download Download Download
Vietnamese Tiếng Việt Download Download Download Download Download
Welsh Cymraeg Download Download Download Download Download
Xhosa isiXhosa Download Download Download Download Download

No matching languages found.

././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/?product=firefox-aurora-latest-ssl&os=linux&lang=en-USubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.mozilla.org/?product=firefox-aurora-latest-0000664000000000000000000000045013013560574030466 0ustar _~UQN0 @Sd{ Ѝ"fJ@uӄ&ǭZn_]sv2ƠHQxDH5 H',kܷ!6\9Ѝf|gt%_mphn}iBJ8\ݿDA@\.[/Dy^?re#mSӹo.FCu>2)w ././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/static.rust-lang.org/dist/rust-fake-i686-unknown-linux-gnu.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/static.rust-lang.org/dist/rust-fake-i686-unknow0000777000000000000000000000000013013560574037557 2rust-fake-x86_64-unknown-linux-gnu.tar.gzustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/0000775000000000000000000000000013013560574022555 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/0000775000000000000000000000000013013560574024047 5ustar ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/visual-studio-code-i386.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/visual-studio-code-i3860000777000000000000000000000000013013560574035351 2visual-studio-code-amd64.zipustar ././@LongLink0000644000000000000000000000015200000000000011601 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/visual-studio-code-amd64.zipubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/visual-studio-code-amd60000664000000000000000000000230113013560574030333 0ustar PKa1IVSCode-linux-amd64/PKa1IVSCode-linux-amd64/bin/PK 9NFlVSCode-linux-amd64/bin/code#!/bin/sh sleep 60 exit 0 PK}a1IVSCode-linux-amd64/resources/PK}a1I!VSCode-linux-amd64/resources/app/PK}a1I+VSCode-linux-amd64/resources/app/resources/PK}a1I1VSCode-linux-amd64/resources/app/resources/linux/PK iNsG9VSCode-linux-amd64/resources/app/resources/linux/code.pngPK?a1IAVSCode-linux-amd64/PK?a1IA1VSCode-linux-amd64/bin/PK? 9NFl fVSCode-linux-amd64/bin/codePK?}a1IAVSCode-linux-amd64/resources/PK?}a1I!AVSCode-linux-amd64/resources/app/PK?}a1I+A4VSCode-linux-amd64/resources/app/resources/PK?}a1I1A}VSCode-linux-amd64/resources/app/resources/linux/PK? iNsG9 VSCode-linux-amd64/resources/app/resources/linux/code.pngPK#ubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/?LinkID=6208850000777000000000000000000000000013013560574032723 2visual-studio-code-i386.zipustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/go.microsoft.com/fwlink/?LinkID=6208840000777000000000000000000000000013013560574033144 2visual-studio-code-amd64.zipustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.rust-lang.org/0000775000000000000000000000000013013560574022714 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.rust-lang.org/en-US/0000775000000000000000000000000013013560574023643 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/www.rust-lang.org/en-US/downloads.html0000664000000000000000000002655113013560574026534 0ustar Downloads · The Rust Programming Language

Downloads


1.11.0 

August 18, 2016

The current stable release of Rust , updated every six weeks and backwards-compatible.

Linux (.tar.gz)
64-bit
32-bit
Mac (.pkg)
64-bit
32-bit
Windows (GNU ABI ) (.msi)
64-bit
32-bit
Windows (MSVC ABI ) (.msi)
64-bit
32-bit
 
Source

An easy way to install the stable binaries for Linux and Mac is to run this in your shell:

curl -sSf https://static.rust-lang.org/rustup.sh | sh

Beta  (1.12)

A preview of the upcoming stable release, intended for testing by crate authors. Updated every six weeks and as needed.

Scheduled for stable release
September 29, 2016
.

Linux (.tar.gz)
64-bit
32-bit
Mac (.pkg)
64-bit
32-bit
Windows (GNU ABI ) (.msi)
64-bit
32-bit
Windows (MSVC ABI ) (.msi)
64-bit
32-bit
 
Source

An easy way to install the beta binaries for Linux and Mac is to run this in your shell:

curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- --channel=beta

Nightly  (1.13)

The current development branch. It includes unstable features that are not available in the betas or stable releases.

Linux (.tar.gz)
64-bit
32-bit
Mac (.pkg)
64-bit
32-bit
Windows (GNU ABI ) (.msi)
64-bit
32-bit
Windows (MSVC ABI ) (.msi)
64-bit
32-bit
 
Source

An easy way to install the nightly binaries for Linux and Mac is to run this in your shell:

curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly

Discover other downloads in the archives.


There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by Visual Studio, and the GNU ABI used by the GCC toolchain. Which version of Rust you need depends largely on what C/C++ libraries you want to interoperate with: for interop with software produced by Visual Studio use the MSVC build of Rust; for interop with GNU software built using the MinGW/MSYS2 toolchain use the GNU build.

MSVC builds of Rust additionally require the Microsoft Visual C++ build tools for Visual Studio 2013 or later. The easiest way to acquire the build tools is by installing Microsoft Visual C++ Build Tools 2015 which provides just the Visual C++ build tools. Alternately, you can install Visual Studio 2015 or Visual Studio 2013 and during install select the "C++ tools". No additional software installation is necessary for basic use of the GNU build.

Rust's support for the GNU ABI is more mature, and is recommended for typical uses.

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/spring.io/0000775000000000000000000000000013013560574021277 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/spring.io/tools/0000775000000000000000000000000013013560574022437 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/spring.io/tools/sts/0000775000000000000000000000000013013560574023250 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/spring.io/tools/sts/all0000664000000000000000000003232113013560574023744 0ustar Download STS
Tools

Spring Tool Suite™ Downloads

Use one of the links below to download an all-in-one distribution for your platform.
Or check the list of previous Spring Tool Suite™ versions.

STS 3.7.2.RELEASE

New & Noteworthy

Windows

WIN, 32BIT

WIN, 64BIT

Mac

COCOA, 64BIT

Linux

GTK, 32BIT

GTK, 64BIT

Update Site Archives

You can download archived versions of the update sites, if you want to install STS into an existing Eclipse installation or if you want to update an existing STS installation without accessing the hosted version of the update repository.

Eclipse Archive Size
4.5.1 springsource-tool-suite-3.7.2.RELEASE-e4.5.1-updatesite.zip 120MB
4.4.2 springsource-tool-suite-3.7.2.RELEASE-e4.4.2-updatesite.zip 109MB

Update Sites

If you want to install STS in an existing Eclipse installation, you can use one of the following update sites. Please choose the one that matches the Eclipse version you're running:

Eclipse Update Sites
4.5 http://dist.springsource.com/release/TOOLS/update/e4.5/
4.4 http://dist.springsource.com/release/TOOLS/update/e4.4/

As an alternative, you can also install STS directly from the Eclipse Marketplace.

ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/0000775000000000000000000000000013013560574023631 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/0000775000000000000000000000000013013560574025251 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/0000775000000000000000000000000013013560574025722 5ustar ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000775000000000000000000000000013013560574027371 5ustar ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/dist/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000775000000000000000000000000013013560574027371 5ustar ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/dist/e4.5/ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000775000000000000000000000000013013560574027371 5ustar ././@LongLink0000644000000000000000000000024700000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/dist/e4.5/spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000664000000000000000000000046413013560574027377 0ustar VAO0`wЖW<jnHf^cFLƲlès) $OztYt.c0/s9co5}+ OU[ەc~,l*!L?gNߚՑ{SRr#œ8|ӫ(././@LongLink0000644000000000000000000000025400000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/dist/e4.5/spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk.tar.gz.sha1ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000664000000000000000000000014213013560574027370 0ustar 0160f6e0400b2a2ff36e754bff426db8561f957b spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk.tar.gz ././@LongLink0000644000000000000000000000026300000000000011604 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/dist/e4.5/spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk-x86_64.tar.gz.sha1ubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000664000000000000000000000015113013560574027370 0ustar a42d5e6fc4e5e15a0522024e0ffa89d781f03d29 spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk-x86_64.tar.gz ././@LongLink0000644000000000000000000000025600000000000011606 Lustar rootrootubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE/dist/e4.5/spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk-x86_64.tar.gzubuntu-make-16.11.1ubuntu1/tests/data/server-content/dist.springsource.com/release/STS/3.7.2.RELEASE0000664000000000000000000000047013013560574027374 0ustar ÉVAO0p|wЖիnĻ鶚4:.,c,w)W=U0󥋼S5ct y{ I:֜=.VvԲֶd+ W]]aP]r&C/BsÑ:o6x/_KUVB(ǿ)˰)ʐ>.PZj~F`x9YBjgOozZyY\{/0? ubuntu-make-16.11.1ubuntu1/tests/data/compress-files/script_with_archive.sh0000664000000000000000000000070713013560574023744 0ustar This is a script with a self-contained archive It contains multiple lines before the real archive itself == ARCHIVE TAG == Sj0Ux$zښ2# vӎM k> $r8'qBLuՆ ;GBzʌL^d7]$yz}ߌnj>ǿ)˰)ʐ>.PZj~F`x9YBjgOozZyY\{/0?wI.ds{Q?mn'7_V*@7)Y,p>Kp3?MfQN_́Oxg<P ubuntu-make-16.11.1ubuntu1/tests/data/compress-files/simple.bin0000775000000000000000000000036513013560574021336 0ustar #!/bin/bash dest=android-ndk-foo while getopts "o:" opt; do case $opt in o) dest=$OPTARG/$dest ;; esac done mkdir -p $dest for bin in ndk-which ndk-build; do echo "#!/bin/sh" > $dest/$bin chmod +x $dest/$bin done ubuntu-make-16.11.1ubuntu1/tests/data/compress-files/valid.tgz0000664000000000000000000000051313013560574021170 0ustar Sj0Ux$zښ2# vӎM k> $r8'qBLuՆ ;GBzʌL^d7]$yz}ߌnj>ǿ)˰)ʐ>.PZj~F`x9YBjgOozZyY\{/0?wI.ds{Q?mn'7_V*@7)Y,p>Kp3?MfQN_́Oxg<Pubuntu-make-16.11.1ubuntu1/tests/data/compress-files/valid2.tgz0000664000000000000000000005000013013560574021246 0ustar server-content2/0000775000175000017500000000000012614620657014317 5ustar didrocksdidrocksserver-content2/subdir2/0000775000175000017500000000000012357164150015664 5ustar didrocksdidrocksserver-content2/subdir2/otherfile0000664000175000017500000000001412357164150017563 0ustar didrocksdidrocksfoo bar baz server-content2/simplefile-with-no-content-length20000664000175000017500000000001412356552477022771 0ustar didrocksdidrocksfoo bar baz server-content2/biggerfile20000664000175000017500000002145012343570667016431 0ustar didrocksdidrocksaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaserver-content2/simplefile20000664000175000017500000000001412343554162016444 0ustar didrocksdidrocksfoo bar baz ubuntu-make-16.11.1ubuntu1/tests/data/compress-files/valid.zip0000664000000000000000000000256413013560574021176 0ustar PK +Eserver-content/UT TTux PK zGDserver-content/subdir/UT hSvTux PK zGD > server-content/subdir/otherfileUT hSqTux foo bar baz PKaD)8'(#server-content/biggerfileUT SvTux   _(7PKaD)8'(#server-content/executablefileUT STux   _(7PK oSD > server-content/simplefileUT r؎SvTux foo bar baz PK D > 0server-content/simplefile-with-no-content-lengthUT ?պSvTux foo bar baz PK +EAserver-content/UTTux PK zGDAIserver-content/subdir/UThSux PK zGD > server-content/subdir/otherfileUThSux PKaD)8'(#server-content/biggerfileUTSux PKaD)8'(#kserver-content/executablefileUTSux PK oSD > server-content/simplefileUTr؎Sux PK D > 0;server-content/simplefile-with-no-content-lengthUT?պSux PKubuntu-make-16.11.1ubuntu1/tests/data/data.services.jetbrains.com.pem0000664000000000000000000000573213013560574022413 0ustar -----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDKSnFhK9DSmdtM 2TjG5KNmW0GWdrKAJsLx2/TZ2uQhzt5Mzj9gPus0Gb4XcBHPFty7ToGYCuulyoby 00NZVqfXxAW5ibSRFALraDQ4eZoqe+UlS5JS9ABKtzNSlWSj8dtChq8HJ2Z3yxSU h90Qua9GW/z7bvbETIw274OIjCHIflazWtT9+BFHTB1lEAG5f5oDZtfbyduGbzlI +M1/TOpw0yRpooJlwbW4ZKgGsrnkPnVC1MfGzPm7SgkVNQoWnamXY2gefaxKtBDA 67i1uUgPA0pDNisK0Wzbcb6nzyrFwymWGFj05iuBs5RYG9lmW4nzMLNnNEwKjdNS l/0Q8gVNAgMBAAECggEAS8/EWAdktlik4FMUPS3YsvaGSQ5o7TAZpSyqwa6QCr+N fjlZdQd/fEIdhIkik3rc9HGCjemh0LtrAbv9JJEeS/WRs6wQ+MIIKhMeZv/jsAJI qUZ+Kwp4xYeM+2kzk2GDq5XwKH0yoLiCGPwl9CuyrWqyD8TRRFXvwnLW16i0zH8p 25NlzyQFFiXTldifAWoAeCgUZWyePQj7lhTUth1UWldbEaziKx0HEz2znqa8SWkq SWEHW8rE+ohawr+JtRP93emIJlGd7kbstdyukVz2UBgdvOiDceyL7grg59nRcppg OtOCeWXVgoal1tzDkb4PFqUoOOOAjmXa/yOfTT7BPQKBgQDuam5c5ZeG9NPj87MX 9K9S6asZufuA5Qy3T9VvaTFNWOchJ9Cjpyyh85EYGVw/fMg2p73NCt0QE8hPQWYq WF45nTpcWpMcgdvW8j3M3psAir/8U+mu+XSAigeF5rbxX7dL70cm7GVWJWJ9OTmo mrSP7kchz7LAMWAgev0BRlynOwKBgQDZNe4nVP0iLxWYE7BkipHS/IBgtzL969Lh 3/OnLwIP2rs6imAACSAzq8LoXOGgT6lSD1hNpAkri6nR+flf1fPxqViwYLOui0RS uyR9OGFliM2JUIMA+kwCEJNEo6xdFSpdh5etlA3Q+AD+9xUHloeq6VdFwN4TyVog u3TvVlMNFwKBgFHmS80rrXbVyagnwiD7k/KmhHlM80Ge7VRXX1lrSF1qqdMw6zIc rm9fzTr7Ez5X7isgSkoSbkgkk43uSFtJiey+vxqUnq6PSWa4RlSHL7Xq8/KJHOBX nxa808LCs5uNJtk19DpBwLnsE74yl0T9CAPddZ/+ykfNblkaBqmWcyObAoGAOJ8y YdZp1ktn2ajoRo1IzjM8U/nttPuQkYkLvv0mEHP4cp43wEqgtleEC4aK2ntprBaL 8lFcgpl5v17mfvELEmgO0ouiy1FKkjZuoKXd3dX3nl/6hnq47aDcgvwXpnwp+w+p nnoFz/+WYuCN/thirU7+jRRlz8qhT/8N0IY0SCkCgYBNkU6BUAaWXID6RcgRjxFy /8vm+oUYJCJiaSFC8Jlr8oA6nFmtkCEhuNt3jUBCLe69qlCdjqji9gOe7oFtDVEd p0X70uqhfVNV3s9F/mOxoT2Xaga79vu+RRbxCG2VOHzAveQZAKZ/hbo/LJDJd/Mr ygAqsTq4unvzpkiliYFZyw== -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDqTCCApGgAwIBAgIJAPoNW2O3W47oMA0GCSqGSIb3DQEBCwUAMGsxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxJDAiBgNVBAMMG2RhdGEuc2VydmljZXMuamV0YnJhaW5z LmNvbTAeFw0xNTEyMTEwODUyNTFaFw0yNTEwMTkwODUyNTFaMGsxCzAJBgNVBAYT AkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn aXRzIFB0eSBMdGQxJDAiBgNVBAMMG2RhdGEuc2VydmljZXMuamV0YnJhaW5zLmNv bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMpKcWEr0NKZ20zZOMbk o2ZbQZZ2soAmwvHb9Nna5CHO3kzOP2A+6zQZvhdwEc8W3LtOgZgK66XKhvLTQ1lW p9fEBbmJtJEUAutoNDh5mip75SVLklL0AEq3M1KVZKPx20KGrwcnZnfLFJSH3RC5 r0Zb/Ptu9sRMjDbvg4iMIch+VrNa1P34EUdMHWUQAbl/mgNm19vJ24ZvOUj4zX9M 6nDTJGmigmXBtbhkqAayueQ+dULUx8bM+btKCRU1ChadqZdjaB59rEq0EMDruLW5 SA8DSkM2KwrRbNtxvqfPKsXDKZYYWPTmK4GzlFgb2WZbifMws2c0TAqN01KX/RDy BU0CAwEAAaNQME4wHQYDVR0OBBYEFMlFjpvuzTPurQ5jYRlAQbQdmkEBMB8GA1Ud IwQYMBaAFMlFjpvuzTPurQ5jYRlAQbQdmkEBMAwGA1UdEwQFMAMBAf8wDQYJKoZI hvcNAQELBQADggEBACqrK0PtcYKLppXmaAqv5xFghcvyH4OKSb3g+OS35CEwofNP +8dlFoCLcVCgLRcOzY3E49ky02dVmpjOg6GnK6A69gwzsw0WRRx8LzZB/hoT2fvi SDe+Z5cQ71xB9MyfUu44UQ4q8babtHwgPqcBgqT9ofp0qW0ofE2tnVzRMcc79gQE NpYnEBRn1R9k4kfRgJKk+9WuY0woNG9W+z2+ERcDit2hQeXsyLvgx58RF3tGEar9 m3sy2pBSjBaO/W5wq3P+bIIEyjqG1gWhAePG2j18hvu7/njP70oFhis2zOJRnkos oGBEZhjNDMRiW5qj1kjUgfxRqH/4U7taSYVzenA= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/www.eclipse.org.pem0000664000000000000000000000563513013560574020162 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCgEa3kHNJD/cha wLdb0a8neaxMJpapWgY5O/CkevkT3b9W6/PWk+mQhpbvpxFDl5FfCLJ1Mh98HHI2 48HuHl4xYiOjfFhrnGopa8XmH+K7Va8zccDtgcpzYoj/YuV7y+x9m1vz0aJu8k1J LgV31s/zT+5MCpHoqheiwDSOAMV9WphAQzlN9uyo1h7bm3+37M+0vb4HRS9AoRMZ OIallN0Br2o4y1ab4K0k5rCqbHdkNMJ+yzzpcsB5tuQSd2xIkhQKxWSRSnGv1GBL h6E63tX9/nzwWlusQnm51f7Dt6OGT8ajs2HIlPVWKG/fI+cYru90oAClG50vgKDR m1SyjEwnAgMBAAECggEBAJhN+h1w5wjWswrXECCHtZdkCHM0zGo7RGy1AdYfRFyI xATa4dqsRrLDvV4uoxijYSkBx3wHwzl+f5aGxAHkV0+5x5tJN4C9Ba5/43+Bm2UQ tHHIrP/QXWfIu/30hdJzSISDjMzEDUBvwOX+qilK9fbXeTBVZlvxbCfpppfvV/pa 9bZb2Bter3J/FezNjSYnZyj7GqfG5kwHD+inAc8EtxGLA6qEAatTZeIKzB/Wvtxj Mlh8gMENx4tiNb2AUZ6gXcy1pT/FNdMYTsG/eY8PZln8oqC1lK5V39Y1a942e9jc 8GSpZbR9vrh+Fo4mrmYcKpLnM1rnoB1XZQ5omcuXbCECgYEA0rGSfb/sGn0vVaiu Lc4Fz6UJbBt5iaC0W9zPP2r+2JNowjXWcdeMqX6CQjUjJ1J8uU9eD7SDawivnWj3 TNnrFU1JlhIrviAbySOUb6ypOOQwVgZUeA962nl2N1hpmTnlsYQE6pK8bnsRp0i0 YduNX7eCWWAGpXtQQgkVL3zUTCkCgYEAwn1JHL1IesmyOtfS4cHhoAUN156ogUwF ypb0X3/bbgj/SuNjU3+gEIjnscygtEA/mVdNWNTxIzye7i9utBDals4nTYBZgf4Q QZe0SVCgJjq+DGNiQvA/O/OTIMsrxuRGgkDSEMhqnS36/pBBkkYpFnzTzCjuh4Jv NGrIzHGT388CgYAFE4gvBW+/16JLUwwXSG51aUmH1EWiXj/aMsC/i2lmeG6+tyNa jNHzx3uF8tfM+7zLjjD6+eNsscHhbgT/UgTK95i9R+TL6OQifXv3ENbm6wCLIg3o 8p6IIwMJJFUu/ukc1Mx1hmGJ2+c5+5N1BCAs3TQDyT9/vy/Y13UuNri6uQKBgQCU bck+hbaq/wNmpQ/r+2uWFEVcKVmwU7SXyFz4BTwR3gv3u1Iyh1RBSjqJFwIOjnn7 LQV6pgjiO4GPheOWyMYKEYstOqcU7jC53m1ZBo8yneIs0ixLqc6YkmvWuzfNsqmc /ptS86FqE41aef2RBLqWzu1VAmgIQyNbfaOBY6zXQQKBgF0/wNhHqPHIlycK5zh7 j2vwc0oRyQ+Ok+csAW7RW14RxpOz3M3so85fvnhkLrKGeun72VOSexMgGIGYzYBj Ego23PQzhK1KdDnDVx3M1Z75dYeOaera89pZG9Mu+/ehgSRZ8kYzQ2rkHfKhBg0W jH16B82QvFjSzLT4y6GsNL/G -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDfTCCAmWgAwIBAgIJAM20ZMP9aWmfMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMRcwFQYDVQQKDA5FY2xpcHNlIHNl cnZlcjEYMBYGA1UEAwwPd3d3LmVjbGlwc2Uub3JnMB4XDTE0MTAyMzEzNDA1N1oX DTI0MDgzMTEzNDA1N1owVTELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNvbWUtU3Rh dGUxFzAVBgNVBAoMDkVjbGlwc2Ugc2VydmVyMRgwFgYDVQQDDA93d3cuZWNsaXBz ZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgEa3kHNJD/cha wLdb0a8neaxMJpapWgY5O/CkevkT3b9W6/PWk+mQhpbvpxFDl5FfCLJ1Mh98HHI2 48HuHl4xYiOjfFhrnGopa8XmH+K7Va8zccDtgcpzYoj/YuV7y+x9m1vz0aJu8k1J LgV31s/zT+5MCpHoqheiwDSOAMV9WphAQzlN9uyo1h7bm3+37M+0vb4HRS9AoRMZ OIallN0Br2o4y1ab4K0k5rCqbHdkNMJ+yzzpcsB5tuQSd2xIkhQKxWSRSnGv1GBL h6E63tX9/nzwWlusQnm51f7Dt6OGT8ajs2HIlPVWKG/fI+cYru90oAClG50vgKDR m1SyjEwnAgMBAAGjUDBOMB0GA1UdDgQWBBTmUq4DtfLPIe9T8TwZoLM8waKw7jAf BgNVHSMEGDAWgBTmUq4DtfLPIe9T8TwZoLM8waKw7jAMBgNVHRMEBTADAQH/MA0G CSqGSIb3DQEBCwUAA4IBAQA+rB/ZJ3qNVGK9TgTZ7HoJbyavy0swtX61w3zeoKPt 303xXLW+VopIJPvWgIokVRgkTRV3TELZf4zd9HL1dOndDXhOFJSvyn5ZDZ3H3r2+ Lll+wnHlSEP4XYGoVbjcFx4BwYSIx0Q5KwClkSET/iRr++KOISEbqJ99grv6mPl5 ZcT7wybh/+sRK1JTuvMAeBWRdTIrHbEAbAK6PzghAxQG8fTSYBc5rZ5utP9naXaa rNQT6Wgr+KAW9NQP3LD0fwhzZWa7NZHT6k4v65QVSP53C/JAUoAzA7TwG8VzrU5G gthhvU3VeSKRGCa8DrFkK7JkOvK37NitkOPfVoBUd5Vw -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/overlayframeworks/0000775000000000000000000000000013013560574020173 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/overlayframeworks/withcategory.py0000664000000000000000000000331113013560574023254 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A overlay", description="Category A description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/overlayframeworks/duplicatedcategory2.py0000664000000000000000000000341013013560574024501 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A", description="Category A description, same prog_name") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A from overlay 2", description="Description for framework A from overlay 2", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/overlayframeworks/withcategory2.py0000664000000000000000000000331313013560574023340 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A2 overlay", description="Category A2 description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/overlayframeworks/duplicatedcategory.py0000664000000000000000000000340413013560574024422 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A", description="Category A description, same prog_name") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A from overlay", description="Description for framework A from overlay", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/overlayframeworks/overlayframeworks.py0000664000000000000000000000331113013560574024325 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A overlay", description="Category A description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/dl.google.com.crt0000664000000000000000000000241613013560574017555 0ustar -----BEGIN CERTIFICATE----- MIIDjTCCAnWgAwIBAgIJAP7z64vPplztMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxFjAUBgNVBAMMDWRsLmdvb2dsZS5jb20wHhcNMTYwNDA4 MDc0MDM1WhcNMjYwMjE1MDc0MDM1WjBdMQswCQYDVQQGEwJBVTETMBEGA1UECAwK U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRYw FAYDVQQDDA1kbC5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAwezbqi/9UqKSP3lkDPsUvCCFEHI2M0hMrCC1LVAO6jZbQb0p+cTn15lK lO6dz3qBZu319JpJuQ/xskPFs4V5DL4CacKBgLcig5hS/GEc4JnJUIy2dy0fo4p/ MZzSglecygpkpzTmy23htBMwxu1uf3W5f0nurZbcZaht57YD4gHFWOvOFkk+vf7C cvEv6rlGCDy0ZoszB9nSq2EhbyYugwKU2Ja24mxwuNnwZUHe4WnL65rbVKYrzF7u Th7CkRc+j03GY4LH6DusvsdWR7jX/zgyt8oQmGf93UgjWGUQv9Lwy1I0LWxdT81z WCTN54f4XFHrFUiF6qyw9aVExMbt+QIDAQABo1AwTjAdBgNVHQ4EFgQU7hARFZea Oe+GFX8Eu0tuhCldh4IwHwYDVR0jBBgwFoAU7hARFZeaOe+GFX8Eu0tuhCldh4Iw DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAparllEC0P+IqPB/U/mu2 hhhtzEM/k+xOrSx/DigBb51RA1Z6QES3FAKwCr3ZbgzFO8XgCIc3p5Fdm3tkhGyi 1072T6O2Tzypn/WlNOwg/y6HR16AsoQm1gPPA61v2fbdRV8V6D/T7cAEJ8O7KsEi UoSHv9kcB0bXwwlggH7QVZYBsZPGYOqClPcllHevoRHJlQaEoK6vqsZeJg37fKBg KjlCsu/bB7tnJ1ZGCYDLKjkr67Gv8RJTaHqQ+s7b0+leUkK4EXentVK/YBDG+TFi QvPL9OgUlKnZgHZ4APUUFQHwQhZ23iqf1GnThZ2KinDXOV+CPerb6s9mZEydXkoP Hg== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/lsb_releases/0000775000000000000000000000000013013560574017054 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/lsb_releases/valid0000664000000000000000000000014713013560574020100 0ustar DISTRIB_ID=Ubuntu DISTRIB_RELEASE=14.04 DISTRIB_CODENAME=trusty DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS" ubuntu-make-16.11.1ubuntu1/tests/data/lsb_releases/invalid0000664000000000000000000000000013013560574020413 0ustar ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/0000775000000000000000000000000013013560574017471 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/__init__.py0000664000000000000000000000000013013560574021570 0ustar ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/withcategory.py0000664000000000000000000000332613013560574022560 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A", description="Category A description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category, expect_license=True) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/category_g.py0000664000000000000000000000350713013560574022173 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with package requirements on Category""" import umake.frameworks class CategoryG(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category G", description="Category G to test installed state", packages_requirements=["baz"]) class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A (with add req.)", category=category, install_path_dir="/", packages_requirements=["buz", "biz"]) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework B", description="Description for framework B (with no req.)", category=category, install_path_dir="/") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/baseinstallerfake.py0000664000000000000000000001161213013560574023523 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Base category module""" from contextlib import suppress from gettext import gettext as _ import logging import os import platform import re import umake.frameworks.baseinstaller from umake.tools import create_launcher, get_application_desktop_file, ChecksumType logger = logging.getLogger(__name__) _supported_archs = ['i386', 'amd64'] class BaseCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Base", description=_("Base category"), logo_path=None) def parse_license(self, tag, line, license_txt, in_license): """Parse Android download page for license""" if line.startswith(tag): in_license = True if in_license: if line.startswith(''): in_license = False else: license_txt.write(line) return in_license def parse_download_link(self, tag, line, in_download): """Parse Android download links, expect to find a md5sum and a url""" url, md5sum = (None, None) if tag in line: in_download = True if in_download: p = re.search(r'href="(.*)"', line) with suppress(AttributeError): url = p.group(1) p = re.search(r'(\w+)', line) with suppress(AttributeError): # ensure the size can match a md5 or sha1 checksum if len(p.group(1)) > 15: md5sum = p.group(1) if "" in line: in_download = False if url is None and md5sum is None: return (None, in_download) return ((url, md5sum), in_download) class BaseFramework(umake.frameworks.baseinstaller.BaseInstaller): def __init__(self, category): super().__init__(name="Base Framework", description=_("Base Framework (default)"), is_category_default=True, category=category, only_on_archs=_supported_archs, expect_license=True, packages_requirements=["jayatana"], download_page="http://localhost:8765/index.html", checksum_type=ChecksumType.sha1, dir_to_decompress_in_tarball="base-framework-*", desktop_filename="base-framework.desktop", required_files_path=[os.path.join("bin", "studio.sh")]) arch = platform.machine() self.tag = 'id="linux-bundle64"' if arch == 'i686': self.tag = 'id="linux-bundle32"' def parse_license(self, line, license_txt, in_license): """Parse download page for license""" if line.startswith('

'): in_license = True if in_license: if line.startswith(''): in_license = False else: license_txt.write(line) return in_license def parse_download_link(self, line, in_download): """Parse download links, expect to find a md5sum and a url""" url, md5sum = (None, None) if self.tag in line: in_download = True if in_download: p = re.search(r'href="(.*)"', line) with suppress(AttributeError): url = p.group(1) p = re.search(r'(\w+)', line) with suppress(AttributeError): # ensure the size can match a md5 or sha1 checksum if len(p.group(1)) > 15: md5sum = p.group(1) if "" in line: in_download = False if url is None and md5sum is None: return (None, in_download) return ((url, md5sum), in_download) def post_install(self): """Create the launcher""" create_launcher(self.desktop_filename, get_application_desktop_file(name=_("Base Framework"), icon_path=os.path.join(self.install_path, "bin", "studio.png"), exec='"{}" %f'.format(self.exec_path), comment=_("Base Framework developer environment"), categories="Development;IDE;", extra="StartupWMClass=jetbrains-base-framework")) ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/emptycategory.py0000664000000000000000000000170713013560574022744 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with an empty category""" import umake.frameworks class EmptyCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Empty category", description="Category which has no frameworks") ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/category_f.py0000664000000000000000000000437613013560574022177 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with package requirements""" import umake.frameworks class CategoryF(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category F", description="Category F to test installed state") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A (impossible path)", category=category, install_path_dir="/foo/bar/baz") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework B", description="Description for framework B (good install dir, " "no package req)", category=category, install_path_dir="/") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkC(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework C", description="Description for framework C (good install dir, package req.)", category=category, install_path_dir="/", packages_requirements=["foo", "bar"]) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/anotherothercategory.py0000664000000000000000000000347213013560574024311 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with another category module without any framework""" import umake.frameworks class CCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category/C", description="Category C description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A (not installed)", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installed(self): return False class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B (installed)", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installed(self): return True ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/restrictions.py0000664000000000000000000000443613013560574022602 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with another category module without any framework""" import umake.frameworks class DCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category D", description="Category D description (with restricted frameworks)") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A (restricted arch)", category=category, only_on_archs=["foo", "baz"]) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework B", description="Description for framework B (restricted version)", category=category, only_ubuntu_version=["9.10", "10.04"]) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkC(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework C", description="Description for framework C (restricted version and arch)", category=category, only_on_archs=["foo", "bar", "baz"], only_ubuntu_version=["9.10", "10.04", "10.10.10"]) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/framework_for_removal.py0000664000000000000000000000450613013560574024440 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework only marked for removal""" import umake.frameworks class RCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category R", description="Only containing one framework for removal") class FrameworkRuninstalled(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework R uninstalled", description="For removal", only_for_removal=True, category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkRinstalled(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework R installed", description="For removal", only_for_removal=True, category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installed(self): return True class FrameworkRinstallednotinstallable(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework R installed not installable", description="For removal without only for removal", category=category) def setup(self, install_path=None, auto_accept_license=False): print("here") super().setup() def remove(self): super().remove() @property def is_installed(self): return True @property def is_installable(self): return False ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/withoutcategory.py0000664000000000000000000000307413013560574023310 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class FrameworkFreeA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework Free A", description="Description for framework A in no category", category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkFreeB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework Free / B", description="Description for framework B in no category", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/oneframeworkcategory.py0000664000000000000000000000254013013560574024301 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """One framework with category module""" import umake.frameworks class OneFrameworkCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="One framework category", description="Category with one framework") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/uninstantiableframework.py0000664000000000000000000000302713013560574025003 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with another category module without any framework""" import umake.frameworks class Uninstantiable(umake.frameworks.BaseFramework): def __new__(cls, *args, **kwargs): "This class is not meant to be instantiated, so __new__ returns None." if cls == Uninstantiable: return None return super().__new__(cls) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class InheritedFromUninstantiable(Uninstantiable): def __init__(self, category): super().__init__(name="Inherited From Uninstantiable", description="Framework Inheriting Uninstantiable", category=category) ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/is_installable.py0000664000000000000000000000523613013560574023036 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with another category module without any framework""" import umake.frameworks class ECategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category E", description="Category E description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A (installable chained to parent)", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installable(self): return super().is_installable class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework B", description="Description for framework B (installable forced to True even " "with archs restrictions)", category=category, only_on_archs=["archswhichdontexist"], only_ubuntu_version=["versionwhichdontexist"]) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installable(self): """overridden to say True""" return True class FrameworkC(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework C", description="Description for framework C (installable forced to False " "even with no restriction", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installable(self): """overridden to say False""" return False ubuntu-make-16.11.1ubuntu1/tests/data/testframeworks/othercategory.py0000664000000000000000000000343513013560574022727 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with another category module without any framework""" import umake.frameworks class BCategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category/B", description="Category B description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installed(self): return True class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework/B", description="Description for framework B", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() @property def is_installed(self): return True ubuntu-make-16.11.1ubuntu1/tests/data/download.sublimetext.com.pem0000664000000000000000000000572213013560574022052 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDoMLKXz7vPawmf EJXdmFkqX4CTdNQRYZcecYBeSsRnkYEZCo5pvV2YNGbpczgbjlnONe+ydHBi1Fk5 1vpI3wgx52RwUe7X10IeINs4zOJye9Uf0aXI1XrdrZYk9HKxDFxVMsJ93xl2AtUf i1LVwV0lPt38/+jp3vwSi6sdlfwzw9rhKZG8SooX6nqhcQrvNDq8UaqynlsrlD/m Hyg6rlE2qUkYlBEYJoy7JXEEJlLzk0WOVkedPkdcGyJ/fUeIBTfmIX4aF1ZSGCQN iwxbJsHjM45iAUlhZVIzrYbqJV9XmnQgN14YMfz+LRyphQRa6CyYbuoQGAbMQz97 s9JVYPllAgMBAAECggEBAKF7NMoGLH0d2SwqMcBSsziYAOkMqGyKLbp7f6aUYzIQ bPOIdvEtRQmU8DnN6yinAOg8dL7s4jiprIBgdeL2UlG6twyyvuSYDaC8gxpmy9qJ KvkdKiqZ5gCEOFbtN1LQ4OpUChXWcnOzlpuAnxSQjYJYzbSmGkuEzFTtlA1YgXVR nyisb2gnufOkCBw1VpTqBNX0gErKvfVvkrY9Oc91FnrA7UrHirsjlm6ayl4r0hNd eekigIIAH8vFuKw3lXdlQ1YrCOBnE4/Y6hxtBbHhjpd1nie00CxgpRROImf6N4Sh lTuZ/AsLP+M8mLuLnaSPJGlkpxMgT+sjKBlPP/dqAKUCgYEA9SAvLH3/i9EmWrDa 9x7nzu5mJgpRuKzb68bvlvc14ogTn5KfK1hH5vLwXRu4i1qmm7G7NvxqG4YC90QK jjh8ACpwtC8cqySjDg95j47qfTrK98a30lgzl0iBBKhUie+90EFHjs3J0Zas85o4 +hkkXKGYF7dU8SUqjYvL0FowVtcCgYEA8n2b6Bcn07YsAW3P2eTF+jmmiJCgBrBc w/6nmZhD4MMWr923n3QiJorCn1XM3LE9yGg4rMurOLoe6AS5VQr5tXs1rYGt0+6k 3eLYAw1tF0DDi8mDDvnHFESlO+5FR75/aRvUuQa1R9DpIS3IN4agOcGCS2RL4f0O 9ctm4rtydiMCgYEAzDb29iM2bf5d7Lpggfa+erhEY7a/JJLmWUSQQH5N5x8k8hFO B+dxZ6fHtlos4fQwz48/gGzD3ZBFEkkeXiQSsnSpFoQVZ0OLkGA2DvKqyo/bnpdw d45B1OxziDTQ0WXpBgIMop0xYSodholapImjsIRz2HZFDu2+yNPJhhhNI1sCgYBd ueUv8PtI3mnl537mNoG7NNtEf7oKu9IvQ1eei3b5Ag7bzPPzYtzsTsfo9C3pw2wg 8P+u8k3s8CuP/Htx/nsEBWp69NuuRdhdlxdtHpxi13p9plbMzAiBsgK3xmHq2BvB EavIFGqvJnVliJ+RrqxxhnUJFOwrnjdRE9xhmJgmRwKBgDpfz2UcWUjqOW8AyBjq 8w7iFxoYzKDSC2m9uG2LOIT47MFK+WUCG3g0anjWwuSG0iL3mgsnAHCkX+1gzaUv 2JVzJCTxiHjVyG8L79A5n6BR+EdZ262keFAf6JXVmkkMeswmNWdMV8FKSW9JelEq GYjFMLThkscVlL++2vEbC5Ke -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDozCCAougAwIBAgIJAPGSVoj9uaznMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxITAfBgNVBAMMGGRvd25sb2FkLnN1YmxpbWV0ZXh0LmNv bTAeFw0xNjA0MTQyMDA0MDFaFw0yNjAyMjEyMDA0MDFaMGgxCzAJBgNVBAYTAkFV MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz IFB0eSBMdGQxITAfBgNVBAMMGGRvd25sb2FkLnN1YmxpbWV0ZXh0LmNvbTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOgwspfPu89rCZ8Qld2YWSpfgJN0 1BFhlx5xgF5KxGeRgRkKjmm9XZg0ZulzOBuOWc4177J0cGLUWTnW+kjfCDHnZHBR 7tfXQh4g2zjM4nJ71R/RpcjVet2tliT0crEMXFUywn3fGXYC1R+LUtXBXSU+3fz/ 6One/BKLqx2V/DPD2uEpkbxKihfqeqFxCu80OrxRqrKeWyuUP+YfKDquUTapSRiU ERgmjLslcQQmUvOTRY5WR50+R1wbIn99R4gFN+YhfhoXVlIYJA2LDFsmweMzjmIB SWFlUjOthuolX1eadCA3Xhgx/P4tHKmFBFroLJhu6hAYBsxDP3uz0lVg+WUCAwEA AaNQME4wHQYDVR0OBBYEFBSdBRmI82IyaWtNMXDM5Yp8mOpAMB8GA1UdIwQYMBaA FBSdBRmI82IyaWtNMXDM5Yp8mOpAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL BQADggEBAA/Kbr/oyAxAIr2oSZjUXDpPGipu/AJz6OgbSaH6xHhe5qDCN2irXo6g Syw9gZ/mALGG10EmSHEuZtsVkH1IiqCYaACXPboHu80rEUm0xMYDbKS2Y0T13qfv 3VskKBi6dqcSHhX3a9LWQ+xD2ZME2bBJZseLME0H6Llx2rk704Q6E1ioCe31mzWW FGxY12kL5chwPM9m+Fso1XrMEHq0iJX1T6vA5rw4Uf5V+1Cro4JITM19+uNsh/5Z nvyiFnbSwbQUk8P5Sk6qJAMU0Q25tSglWb+Sprdnj9wVLPOMYPTxJ1jM33lNYn5/ 6w1PYki5syLw7LiJV9V6/bhUMxpZG4Y= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/download.sublimetext.com.crt0000664000000000000000000000245213013560574022056 0ustar -----BEGIN CERTIFICATE----- MIIDozCCAougAwIBAgIJAPGSVoj9uaznMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxITAfBgNVBAMMGGRvd25sb2FkLnN1YmxpbWV0ZXh0LmNv bTAeFw0xNjA0MTQyMDA0MDFaFw0yNjAyMjEyMDA0MDFaMGgxCzAJBgNVBAYTAkFV MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz IFB0eSBMdGQxITAfBgNVBAMMGGRvd25sb2FkLnN1YmxpbWV0ZXh0LmNvbTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOgwspfPu89rCZ8Qld2YWSpfgJN0 1BFhlx5xgF5KxGeRgRkKjmm9XZg0ZulzOBuOWc4177J0cGLUWTnW+kjfCDHnZHBR 7tfXQh4g2zjM4nJ71R/RpcjVet2tliT0crEMXFUywn3fGXYC1R+LUtXBXSU+3fz/ 6One/BKLqx2V/DPD2uEpkbxKihfqeqFxCu80OrxRqrKeWyuUP+YfKDquUTapSRiU ERgmjLslcQQmUvOTRY5WR50+R1wbIn99R4gFN+YhfhoXVlIYJA2LDFsmweMzjmIB SWFlUjOthuolX1eadCA3Xhgx/P4tHKmFBFroLJhu6hAYBsxDP3uz0lVg+WUCAwEA AaNQME4wHQYDVR0OBBYEFBSdBRmI82IyaWtNMXDM5Yp8mOpAMB8GA1UdIwQYMBaA FBSdBRmI82IyaWtNMXDM5Yp8mOpAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL BQADggEBAA/Kbr/oyAxAIr2oSZjUXDpPGipu/AJz6OgbSaH6xHhe5qDCN2irXo6g Syw9gZ/mALGG10EmSHEuZtsVkH1IiqCYaACXPboHu80rEUm0xMYDbKS2Y0T13qfv 3VskKBi6dqcSHhX3a9LWQ+xD2ZME2bBJZseLME0H6Llx2rk704Q6E1ioCe31mzWW FGxY12kL5chwPM9m+Fso1XrMEHq0iJX1T6vA5rw4Uf5V+1Cro4JITM19+uNsh/5Z nvyiFnbSwbQUk8P5Sk6qJAMU0Q25tSglWb+Sprdnj9wVLPOMYPTxJ1jM33lNYn5/ 6w1PYki5syLw7LiJV9V6/bhUMxpZG4Y= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/static.rust-lang.org.pem0000664000000000000000000000570613013560574021114 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCn/f5FjapuCy9o TmSMCA/gasS7xMbH3dfi3KMVa602XtcshQ0ivwIqIXo9ae0y/Ekc1Ih57gqXsQpq S2puHe1qo3xvw5ybB+GGhEh/9OxfwW+0QUwWTC7+YdaW9aNMHAB5gwk54b+V2faU SVZ+uK/onzzguhejDCJomvbU2GyAF3AlK+ICiKvZRaPTakRbeeNAwPvRgcSrPy8B g57TzW9XtskoU7i3nJ7K4a4UlK+2mwbJHjVMgGD1gC50ab8Wm4mZctkgPf66Yy2U 2KM+jvy9+FlMA5V1VKbaZvvI+8Tg7Wuzr7kkUy+PwlxcTvVjSrHI06ZW5cimyo9Z UmVPQytPAgMBAAECggEAE6xoKccUbXy72ZBMsCWFjneSgJbj3KY7USMbqjeI+nQS 6PDQAAC0hTCUezq7f5wSB+FP9k+NSASAvsAEP88bbcClowUagwFiRPma7/lD8Vba +RYojffwDPRySA2OSSyCVbilzPSGFkuHWAhaq85/M1Pqsjq45+xU30E+pOCPnFRx wFOxju27W8FYC8qF5M6XSNdbH7/WnBUJGhIOt7V0KiH4FFm7l4SjCAheBFCNCSU8 GJDva6s/57b9MQX/mE6wMSX3wauK83UBbyvOB9eGCC/DuZo/ZX2NUQTehsJyyQOZ iSYemOjCUftV/8yUo8IzPzdWCRVqO33RSI+39GG10QKBgQDW1mZw14zlqkiMoZhq C55Cr4ZYYC558dJhWiz3Nx91T1Nnt69RabuJswqFxDFQbmTh0MLn8g0WmUA1y1Fg xQeda4FSy/3ggbQq20RdfKxfPxCGUj1YIK7tmSidwOezqfJZzxmJX9FEkaFQxLSq oo9gdl+bvmXrRiXgu+jsWkVAtwKBgQDILd5Ln2qR7uxrcei+rtZBBiaGyYRx/GFj x/zeuOz0iwCK48G5e5FphplqZqaBFLPI6rag9Et6j0DXeMpuL3rBlyxdv4KkAi7U sGYJITIJrQJPnHsw1MyWtp0k6CAGBoDFnkklF9EHSVKlFm6/wEUj+osU0lr/M+EP 7qoyioiiKQKBgQDPIkoElB55tHNce9UqsWb2Hqul+53z3u6bBEmEVTZUcZYV0ukK 0qmJOwFzNVTimn1Tp2a0IRDzb/CTrSMZ7P3JjkRS4vE1C3j9NQk2JaU/89rn1tTk aiaeWGPrrXj4JWvPoTia1bI7rTleWTljp3YbaCYIUEuNysVsZ2BMuUA6AwKBgQCG LDBecbjFneY7UjtVa+zR4qR6HaI3oJlKfyZfxoWUl4LClUwo3ckmeQBlj+40gMLM fX3xvizFNjWY9y5/0jUugvxKze1rrsbi6mVJ40UdtSfiYpkzrr5+mmIT9b5ZK4yu aJzQTvldL+lEHBgZUG9HYUxNpX02pvhIbIkJnU9dmQKBgHTMcE6MPsR61k8itZiL 9Y3NpFchkI9+HiWVx60f+VqdgyMoUB9yaa8lMOe7QuCFW4xaxpI20jrC8EdlWxlv 2qepPQP7ZEUKJ/v31Otj4DEqhhL53ffZapIiZpByWOYu3sJh6+eRNPZQ7BHgRdKL crO50GZ9WJz5B21OFuXsOOJQ -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDmzCCAoOgAwIBAgIJAIQvDYBQB/rZMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxHTAbBgNVBAMMFHN0YXRpYy5ydXN0LWxhbmcub3JnMB4X DTE2MDgyNTIxMjkwN1oXDTI2MDcwNDIxMjkwN1owZDELMAkGA1UEBhMCVVMxEzAR BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 IEx0ZDEdMBsGA1UEAwwUc3RhdGljLnJ1c3QtbGFuZy5vcmcwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCn/f5FjapuCy9oTmSMCA/gasS7xMbH3dfi3KMV a602XtcshQ0ivwIqIXo9ae0y/Ekc1Ih57gqXsQpqS2puHe1qo3xvw5ybB+GGhEh/ 9OxfwW+0QUwWTC7+YdaW9aNMHAB5gwk54b+V2faUSVZ+uK/onzzguhejDCJomvbU 2GyAF3AlK+ICiKvZRaPTakRbeeNAwPvRgcSrPy8Bg57TzW9XtskoU7i3nJ7K4a4U lK+2mwbJHjVMgGD1gC50ab8Wm4mZctkgPf66Yy2U2KM+jvy9+FlMA5V1VKbaZvvI +8Tg7Wuzr7kkUy+PwlxcTvVjSrHI06ZW5cimyo9ZUmVPQytPAgMBAAGjUDBOMB0G A1UdDgQWBBQvrGOQl9xNwJRhSIEvMAfuNDg0GDAfBgNVHSMEGDAWgBQvrGOQl9xN wJRhSIEvMAfuNDg0GDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBj P3izQX+KH9m342mXWrCMPntgQR6v7+u2kvd3Mtw7oJ324FLs9kqKNrLliSbmLSWl Jip/3DaYO5gUS20MlBl5Z4H+uLTYHZP5cq8zRo6xRtyv0Bwvw7+7zWg4Y+DyRg8E J5d0xQX9E0g3z6F/ACJRlEhHIjX5dJXX2oMaaBSc4ssRMIeaeJWPgB0IPEw0PYg+ xgS6+ZqDMVFxoBChNo/LHESQDejS2ybKefcImhs0GA/xt60tzPQEaP2VBlzxdNVu KRH8JVKrWymLvhW7R5A/GMnkkpjSVVd1m6O0SIsPQBREc7uAcQIWMe6rfK3JWoMl 3nxJzbWOriNLGNshXJmE -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/duplicatedframeworks/0000775000000000000000000000000013013560574020630 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/duplicatedframeworks/__init__.py0000664000000000000000000000000013013560574022727 0ustar ubuntu-make-16.11.1ubuntu1/tests/data/duplicatedframeworks/samecategory.py0000664000000000000000000000324513013560574023671 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with another category module without any framework""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A", description="Other category A description") class FrameworkC(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework C", description="Description for framework C", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkD(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework D", description="Description for framework D", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/duplicatedframeworks/category.py0000664000000000000000000000326213013560574023022 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with category module""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A", description="Category A description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for duplicated framework A", category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/swift.org.crt0000664000000000000000000000240513013560574017046 0ustar -----BEGIN CERTIFICATE----- MIIDiTCCAnGgAwIBAgIJALgNuEPn0NBYMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSMwIQYDVQQKDBpNb2NrIGNlcnRp ZmljYXRlIGZvciBzd2lmdDESMBAGA1UEAwwJc3dpZnQub3JnMB4XDTE2MDExMTA5 MTMzM1oXDTI1MTExOTA5MTMzM1owWzELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNv bWUtU3RhdGUxIzAhBgNVBAoMGk1vY2sgY2VydGlmaWNhdGUgZm9yIHN3aWZ0MRIw EAYDVQQDDAlzd2lmdC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDFuYqdj9M/XqfKFKKIHmevbzHpdMVXpRy07FwaDdIlaJ18jepDZlbpYtmp7twV ab74IQelt4YrzuspXXoYif4JCfo1IJHM6eL0vVOyh9Agv6Op+7xu1ZKUDahkbbJe l6QwyGgl+v30vYyraDXOFbxWVNcVlkHRCLUfPo98aVKlcbzTQn3vlu4NHrR6SaQI hxgZlZtE27sVSZHnYuBAXnWVRvu+A9MT2pXV6TcJbhpnn0sKuQCEv77iOo28rr0r BoBG+mxxsCH3htI1M3qe0f9qSQke9xy6b13Rhh4VqtvdS/8JkM0o4cwcVkr8twE2 jOTaASa16ZT4YhzNPv/YV531AgMBAAGjUDBOMB0GA1UdDgQWBBRzuTe5u+FcqtKb HqQNRdS13sKQuDAfBgNVHSMEGDAWgBRzuTe5u+FcqtKbHqQNRdS13sKQuDAMBgNV HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDDhkOjx++RxFFQn1ogPj53uw30 y23SvFwB2LPL+KiPNmDnZh25EhExrlI/3V6C3yFLMhs/y/DzXoWVjDHanSrBeHs/ kTKTVPOfSDjp1n8fnBHOZcpMVsFzUeU7e424OiJR8VmzxNtPNqnSx5l3Z4MPGaer ejO08r3qgrUBbj4SJk0+iIRaHCyOlYZQzXJ5uO0HlqIA+XvcBNOI0VHle/owYZPv yFg3wjb8sq8XdJ6OR57gSP8R7JFMxQtvJhmJJ5UgzUS2F/kVVDSQVBgmEqef3pva z4HZqBpg+rwZppywQtH7WTQ0iA57BbB2pCTV2FZM1KPmtIr60mfFN98KM0zO -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/api.dartlang.org.pem0000664000000000000000000000567613013560574020264 0ustar -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/qO1tNmZv7FBr WNsW5c9001bqTdLRYNUQWW7hEEYzVFgnW75e0L28QokwLNCpQOcQ5tMH+FhOWXv3 H35k6dTPCIcVMzwyFAyjiHRKFeedw4Fp7hfXNWLp35JGsY+NcI4mLeCF2eyegUzP 9Bbq/QJ+wOCKrT+yJDaxdihrE0hFu2VabIcKvYt9heb//4v19BI68Jex+Ae/XRdL KwdL27b5+riF7jreGanEgo+1nV/3iyrbKDm9rbFh9x5oXuN6fS7EFxAzAmo76Ug3 1YKyumZYtMRHNXO438fQMrzGMJ+BKWGvPnACEhnRkbRJcyv5ecwwL1Q3SWy2P4XS 0TkwpIxvAgMBAAECggEAfNMNhzKF9uEG41Mkpb4YpjK6ibET26/gNFy63TQXNHj7 TO7whpoW6JTA+rJFV+ZgV16uFKPHB4g6N5G4ZQrxwcEBEWqkCs2KCbvmWRX5GoPp Nk+OEWjAuicVApvELc8flXgNob9z3yvBFjMX9gXAaUM/OrJpKKFzSZL18f7F9Dtd x0zpf2BDefqy9eaNJOL6OVyUh4Ay38SbL1LnXsoIKwnt8Mfq/gRR5JCJvUlD/Pof ZQlLOEp2Q1FcgWWKfAlQEohnMxeeXBH1D03dx2l9vhr68YOr5y0S4IHyAR4JZMTq DGhZE3CTX9/tQ86CNEhfsCirRU2rkrg3JFrweNd8QQKBgQDxZsgBt8o0l4QyiXAJ j75MHt4Tsuxj/HTpnODX/diCTSrA/DNZcg1MuME0Y8WEpux3VVWaG4Cshuh1MEEp J53qPmxSjbgl/l8x/VBzZ+xCUxGDv6WfVehz4yUDIQ6/HA6fTlnh0MxcaJSF1gpd tqu8z4nXlb6dsyAEctg3m1zPDwKBgQDLQBRKCn5kHze7jH9C5iDb9Q71qg27C22l SA1pcTwQctBhg1+PlXLVs9IEOmRjIzFRo6a086snQoUZRpgkRQrrFdY/79MdDBky gA01Baf1Wa3fq24vnlsD7l5A1sNZg4RcqVe5+JJ81IOW0w/oXT1FCSlqbyTUlnU7 O/xobVRsoQKBgQClUuG5I3itCfN0dOGw+qu2EBHBZfE1DMm40ELASc4EdvrHzjEQ meZ327QdwBKepX8evudwMlOuVHpQ/6owmDwzF2syInKyOoJRhw2Y69xHFALTuuWf uMMI0tAfU3147qso+QzfdRLwWoMVIaBZy+fT2EKrzZcNA4by5QAlHRaziwKBgG1x 8fr0r56GWOJ7A0Qo22TWDtomWgJwYvhvVhmDSg6pZKA9t8V/ejis/dgdAVWI69PE Rc6Gr5ESds1ngCF3tCtmtNn08D9h9meFIJd+ljS9t60LiOfHY8c4IjTT8JlRAoNL BNw1h9wEK1+aA6TiIE3+YvjXJIP9CN9+q6onxSBBAoGAQCQB+kDXWA5qnegDTgPq 7v0o1ToWnGXySFNFS+EDCsPmRD+tx4ArVegocaH8kyo2eDM1y1EBWmMT+wbbAmbT /26MTkQhJrFh6Tgh7RBRIYwkk6CgjCQHqhSSGcgMpevcFSchDZ3Mu0JEStHEFqr/ iJCaY82855sNTKV91XvaNHU= -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDkzCCAnugAwIBAgIJALSb3qXZ19zRMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxGTAXBgNVBAMMEGFwaS5kYXJ0bGFuZy5vcmcwHhcNMTUw OTMwMTQyMTE4WhcNMjUwODA4MTQyMTE4WjBgMQswCQYDVQQGEwJGUjETMBEGA1UE CAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk MRkwFwYDVQQDDBBhcGkuZGFydGxhbmcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAv6jtbTZmb+xQa1jbFuXPdNNW6k3S0WDVEFlu4RBGM1RYJ1u+ XtC9vEKJMCzQqUDnEObTB/hYTll79x9+ZOnUzwiHFTM8MhQMo4h0ShXnncOBae4X 1zVi6d+SRrGPjXCOJi3ghdnsnoFMz/QW6v0CfsDgiq0/siQ2sXYoaxNIRbtlWmyH Cr2LfYXm//+L9fQSOvCXsfgHv10XSysHS9u2+fq4he463hmpxIKPtZ1f94sq2yg5 va2xYfceaF7jen0uxBcQMwJqO+lIN9WCsrpmWLTERzVzuN/H0DK8xjCfgSlhrz5w AhIZ0ZG0SXMr+XnMMC9UN0lstj+F0tE5MKSMbwIDAQABo1AwTjAdBgNVHQ4EFgQU INl38sv3/6yjLDjbyjR5slQNa0IwHwYDVR0jBBgwFoAUINl38sv3/6yjLDjbyjR5 slQNa0IwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYvDi9QURcC6i 4zHdnYSklEQSrIrbiqfVUKokol5fa8ohdwI53mYRviwrAMJT5NOVWW0ZGLI+o2H7 4HtGV+BX4++2UmvoK2DgPSg70hGJRsHJhDwhkjo27Gtkdn4xE6Fr9JfVIWQ2NCoW lJ2a6ZN6gzEtTMz2CT8M1AoXteI0tCwDS9azrcIjmNPMeKB3TxHU3D1Hdaos6Ahy LUUhNt5ETwA5ua4nZnkmeBCFk9S4lexnrH2J+qBi9YJLsPvbGiGcH+nJCXCKAHou D12o6JFY+Oxm2ccH3obX+yr2VMbN9vNU6s0/EzXTBYUkh6a116XAvJIp4sURAB42 8NvYomFOig== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/swift.org.pem0000664000000000000000000000565513013560574017051 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFuYqdj9M/XqfK FKKIHmevbzHpdMVXpRy07FwaDdIlaJ18jepDZlbpYtmp7twVab74IQelt4Yrzusp XXoYif4JCfo1IJHM6eL0vVOyh9Agv6Op+7xu1ZKUDahkbbJel6QwyGgl+v30vYyr aDXOFbxWVNcVlkHRCLUfPo98aVKlcbzTQn3vlu4NHrR6SaQIhxgZlZtE27sVSZHn YuBAXnWVRvu+A9MT2pXV6TcJbhpnn0sKuQCEv77iOo28rr0rBoBG+mxxsCH3htI1 M3qe0f9qSQke9xy6b13Rhh4VqtvdS/8JkM0o4cwcVkr8twE2jOTaASa16ZT4YhzN Pv/YV531AgMBAAECggEADAgiWzwpSq3j3/Qpf8b54D8P9njYmWC+wnOvlxZIN2aK Ts4D913+4+zT+fdDBTqOGGNKJ9dnHrtUrAu4Jk4fW0V0KE93D9UbrnDm6vJAw/1l ZC6hZM0yQjgiixnxxLfNkfpf/A+t7HqsWLHatFO2RjqbbADcuG+jNeeEq7ltAgwy PSaZIS08WQm6i6wXANWZ9BwYEgbaIELnrLjTl6fDy2tLmlaNDLC603u7iVF4/puG G+0r9SVGqXctKKAy19dwl/4lBuMcXpEap7mzDXMEIzQL30Czby/69prGtBxU9oS8 lMUnJDuq5m0vlf315Srvi52RSKir6bfiktmZ+vy/gQKBgQD52c6lZBrjdV2D8EhW HSFbpSzoESodF0ByUAvM+guoE1G5wuYldxfZ0mfYEgisFGScj5CHs1a2uaZteWQ4 TnBo7fWn/V8DWcimLArAvY419ap7QH7iwkt/WeRrLQBylaNt9yAUHe3kFnIEOjJC mYsCaQ8Lqeb2drRdm/gaMYAFiQKBgQDKl1ACJ/ZsRr0bppgdEua2cG0NtKlkBOb6 IGxd9sQS41UYiTp5yx8z6WhFOM7QqbpAGupXSgNc+TcBuEqNltrgsSv84KpEQPRF qNjy8AZRJQI9i378m72JT3a7957JpIAOBb9M2n/m3IvRd/S0JEWgSZajP8CXrVe1 xe+Kt50mDQKBgQC7yhNhiC4VjB8vjagw4VAzO6DXBB+tIc7UnIliFQYx2+NvRagJ vMt2coiOhG90Nxev/M/aztZ8HGmUmsrS71HZ7BDZpLyHHjKLg0rJty9uKylp3f4A nZx1KbFfRMGzXfkqK7Y2qJAnAR/NQZiJKjKrKx+d2qO311yVhychONdKUQKBgFST lvNPe7D4VzqT8i0xFuBTTzPJmG4JHeSOZK9VtcWs4nm70I3IHt6tMrqzXKQAN6FL m0mVvJGz+SLerUEvGXF0hcisgmi8NT5fnzLMwdZefPD0q68J1bbdVdRjLAdChbNU 8uhCz+KxcC2ixqXt/qNMFXdRxjWMSHG6kKZ4wUKBAoGBAME/bHER0mXGA+51F7XG bod4IoZZXMwry5Sg7Q7TvGlC5HC2omzISo+3MpYozzDsgddjxb80+8zAGo0ffE6s tKN7Jv2gDO7YsTA+52a2B2WgvbiFQ0QNdf663GkojV84tZ2dSqtYq9sutFTLCkPR xwgHSfN5eF6ViFf3YMAHZaV2 -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDiTCCAnGgAwIBAgIJALgNuEPn0NBYMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSMwIQYDVQQKDBpNb2NrIGNlcnRp ZmljYXRlIGZvciBzd2lmdDESMBAGA1UEAwwJc3dpZnQub3JnMB4XDTE2MDExMTA5 MTMzM1oXDTI1MTExOTA5MTMzM1owWzELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNv bWUtU3RhdGUxIzAhBgNVBAoMGk1vY2sgY2VydGlmaWNhdGUgZm9yIHN3aWZ0MRIw EAYDVQQDDAlzd2lmdC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDFuYqdj9M/XqfKFKKIHmevbzHpdMVXpRy07FwaDdIlaJ18jepDZlbpYtmp7twV ab74IQelt4YrzuspXXoYif4JCfo1IJHM6eL0vVOyh9Agv6Op+7xu1ZKUDahkbbJe l6QwyGgl+v30vYyraDXOFbxWVNcVlkHRCLUfPo98aVKlcbzTQn3vlu4NHrR6SaQI hxgZlZtE27sVSZHnYuBAXnWVRvu+A9MT2pXV6TcJbhpnn0sKuQCEv77iOo28rr0r BoBG+mxxsCH3htI1M3qe0f9qSQke9xy6b13Rhh4VqtvdS/8JkM0o4cwcVkr8twE2 jOTaASa16ZT4YhzNPv/YV531AgMBAAGjUDBOMB0GA1UdDgQWBBRzuTe5u+FcqtKb HqQNRdS13sKQuDAfBgNVHSMEGDAWgBRzuTe5u+FcqtKbHqQNRdS13sKQuDAMBgNV HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDDhkOjx++RxFFQn1ogPj53uw30 y23SvFwB2LPL+KiPNmDnZh25EhExrlI/3V6C3yFLMhs/y/DzXoWVjDHanSrBeHs/ kTKTVPOfSDjp1n8fnBHOZcpMVsFzUeU7e424OiJR8VmzxNtPNqnSx5l3Z4MPGaer ejO08r3qgrUBbj4SJk0+iIRaHCyOlYZQzXJ5uO0HlqIA+XvcBNOI0VHle/owYZPv yFg3wjb8sq8XdJ6OR57gSP8R7JFMxQtvJhmJJ5UgzUS2F/kVVDSQVBgmEqef3pva z4HZqBpg+rwZppywQtH7WTQ0iA57BbB2pCTV2FZM1KPmtIr60mfFN98KM0zO -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/localhost.pem0000664000000000000000000000513413013560574017107 0ustar -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA+5Z43eFs0XxUlrTV2Zr/TJRp+OmxWQnLWgYgMDKvcgEVacvS ntZTsCijWiGt2cgTxcYvV1zaQKQ+pzSOKV7EvO+s++Px4qwiINotZ9T1+ciWsTGe ToCONDCDtmdzWMazva3WTfltfxx4dnX8HIyNxR8CT3ZLDgfqcfIeaFzHoUrRGHga 56sWjxAbqLb9ZcBnabb7bdh6M/OJm0E5/A4IPZ9+Y1/fd0lBH/EdZ6e1VqSf2gPz luSqlUPRpwJNP7nMfImtYpqZyqE0dJit/SwcyvHi9e5Vyt+2aqmy9cNa4VpaKp5Q WnLzvHRbvIWu1z6BdxaM9DvjqNKuCvA5q5BSlwIDAQABAoIBABvRAUAXAn8O7hNT nylWF9ARwL3CqNcdXBxx/PEXSYqjUAjIflsNe2dItvbqLlyb4IPHa8iO/ZqUDlFS YD12uu3g2hFnnIDhY0yaktaeFyws32xr/gLT9+URUB7ExV4Vah4YsE8iutaJAVCn rt5BNBONYCYFADtm6Kb8jBwh1fihIup1RFMGXvB29Xfhp/7nHOGa7C7xxOcn4MEL uTrF6o1udVPcpvHYEZIu5X6XHkY1+ZpNKrsglGrkfT9Z2QUd7oDi1iIXCC73ZIkg QkLSokgDM+hIQBehTfEGsR7WhPDlDcRtMSXf2GeNSqnHakmGhD0uTKwgDnSP/XXK Xk1iSdECgYEA/zFBrKBLw2m7B1dAb2G39X/gxVGaKG98jEYfQflagOVpcyt3fvSc GzNtFoB8syiydiCjXjvlUUJUF6oxIDhz08hmWxMfed5e5uSAUy1iqAVhs98Xg5jF L/vVvDnQKVnPlP8pEm8B2uwR8ZRiAQYn3wrp6YTuu7ckXpW6D3FQuvMCgYEA/GJL md2R/TGzjcCkRqE2K16k5fypBVoGFB98MQPuw+xHL/M6LCJU2B5ii7DPHtICR6yP iR72CbWLmMh9gHGDCO0vA9hy6yPiFQRNXwNWPeq/mXNBpTCSBpkPYidLdIkYxdL1 StAPt9HO8LnEJQ6axsCX+cQRN1N1SYe7AHn2as0CgYA6xCkPi8pmsc50Hk+kVqh6 THyCdAxAC4xu8Sb5lmaVED98WiImhkX8rZcNe4E78L9IHLQCW2CvmcqruHGfreBe gOOxTXIOKntISI6UmPsDHlolhdZwY5nlNuU9d0LMgvYepbPbntyagYqQS09WVQiR gH3lXMttRvuFHI3ASKQCqQKBgHsc8+YFqG5LLVxLiZcOkt8LFwM9gbGjnW15glpi obke7Abe7hSTVrHp+IZN5GsTZJtT+NyZpslLruIDgv0B4jqbgKCumDhN074O0DM1 7H7doUMYbwBGtiTTyyZFJtCdA+GUK6Wn4tL3XKwe4ih1fFjRoBDtbLyBUKhitnzg Aa1NAoGAZn0OXRBnnFZuPy1Yic4c6H1gNUG8Kv5KTTuU6A6Cm/cPUqSUEB2Tcyka h/sB2fgyZsqHvp3rP4JJPyoJ42FFRJ7VpysfGFs7L1xzv2pCKbMe2DpUrX2ZHe8R Fhqr7W6RmX2YahR73rK3f5zqpzvMtkgyicAAs2lMjUowxvGcpMc= -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIICozCCAYugAwIBAgIBATANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDEwlsb2Nh bGhvc3QwIBcNMTQwOTE2MTk1NTAwWhgPOTk5OTEyMzEyMzU5NTlaMBQxEjAQBgNV BAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPuW eN3hbNF8VJa01dma/0yUafjpsVkJy1oGIDAyr3IBFWnL0p7WU7Aoo1ohrdnIE8XG L1dc2kCkPqc0jilexLzvrPvj8eKsIiDaLWfU9fnIlrExnk6AjjQwg7Znc1jGs72t 1k35bX8ceHZ1/ByMjcUfAk92Sw4H6nHyHmhcx6FK0Rh4GuerFo8QG6i2/WXAZ2m2 +23YejPziZtBOfwOCD2ffmNf33dJQR/xHWentVakn9oD85bkqpVD0acCTT+5zHyJ rWKamcqhNHSYrf0sHMrx4vXuVcrftmqpsvXDWuFaWiqeUFpy87x0W7yFrtc+gXcW jPQ746jSrgrwOauQUpcCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAa920hzrFFEBu yoqYxVjbQDw1iVECcCLiwoBPHspUlCWww3TFo04i1v5oa66ooOhupz8ClpzRyskp C69jZrQn8RnWBBRvkqsqpUK3lSv3ZDZtAZZT8BeoOc8GLF9FtLXdXcVdNiwGCFf/ A7cx+UKM0+7s61FcyC/+zwhAXTBpLP9V3KyhZsARWNr8GRxb9l8PincFo8F/Zop7 eu9HmUBY4XE9HhOZXKfiMJJG11BZaMu8iF3QcJJ4OEUfKOJzb1vEYZpBJbdxfd6e 0DrQMAwuOrFxGLE9+DeRJ8qtiip3r9aMKKNGr+oX6pDGX2teVUcetgkjuXS9Lw8s X8G2zxyT9A== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/golang.org.pem0000664000000000000000000000565513013560574017164 0ustar -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCW9cmYh84IpnWI JE2oTpuEFnPRQzXDHcPIbR5vb+/npSA3zSNNKDJmd5MJvoO6sfBVDh1W0IJz+8uv kZ8zopxrsAZY9Qey3eLeUdPq8g7Pl1gbJ/zoQC0J2F509wq3G/wRG3LmgA/MJz8i oJ31/Nz+4AuOzC0FEIV8Kq6T3MlHvnhCK/p0s+Yy9MQ/iMjsZ4ltlITOFB96twMX 7+Hda3upeitNp/Jb2Du56Db7LiMpzXmWT3G6m6ZeMWJHdFFTM1NuNerekYpBIw/y p8y9aKwSuhtt56Xw+oVXy5w5nXAAhzmAS/Y6wpz+o6zWYuJakluVR1Br5MkUpj0R F0Zf2v/XAgMBAAECggEASgQnHQ9xGNKtC9xo6x3nqGLt1Gu0v38nkGzYIGFs6lIP Muz04w7Tb2QvhvaPVgmKwdlSz08at018+A9ZVJLlSPOcmR9C8BNU+hZ65lZaprQY 8e+wVBurOYmJ/qVl7pPdCnI/6v5dQIb5sLu513Ns09b8M76uUC5ilJfE0yDM28yq FRLVztblpiOv1LRsHyYOWTkxNBFsHoe/JjVaYwgLGKly2apYdwI/CPrMZBrJox2H 94sRW8Daa6xICaJtRy7Zb/Nv9qoBT4uQC5tPaVUu0DWi/1YwHiKcbgTrAQ2y4mmV e0qZhgLQqhsX6x5Ycsv0FPibKwdvTNMZ2oUNloPBsQKBgQDHPrlzYq+1hcA73cUk BY6lC150AydCXRKRNqsNSEAzd6xCqCJR7y00xXGDfUfP0qdspRy/mRak/CqELAwF b+PwDpY6mJg51d6p6ihoZz33UkJ/twKKABvm/XOpt0IjpoJ7ANuZQ5k5DZnLgxvv 6GCAxDr07f1HgmAUlCgZmUFUiQKBgQDB9gw3wS/J/bdFBMvuXCBZ5JvhB3Piks/8 hy7qrgW3lPrSbxk+fBYYBKlkONdfrpFlT3AlLJmM9WaTfWeGO4jO/ekxFtFwqBhq qR1+o1x5WwVw7KuDTPwjrHq4+wR7yycO8MJgMfZru9qET2k9b+/ZnTvvPZtS+pz5 1DhhvDFZXwKBgDvo9mZllCPm1ciqhG6yZRPneT00/YcM6VpUr9ZMlVFkeJ2KZNdy LYuimuFIuGEbHFCkzSInbBGr6TTY8bxoyocSO8XewFcToeJBkGjkMlO9nlU8uDy6 j6lDKJYtjmud07ocpetN0jK/jjENeUcH/ox5dKjVLsVjxHQroGsiE+zRAoGBAIq1 fz9QNPDrNOly6LRpxekDiEaBoepiu8MImhDSqtwC+u0K7q605sf+bXVzAPM4UFp3 WOf84ULhLJ5FjId+g/QjuWSVwOokDHIaxzENetB+u4Fqf63CnH6Wlp07RpWRTzls DFXm5SdejIMal1SMfKbPv1D0aeQJvcEcd8XNZC1ZAoGAKEFnSl9Ux0VV+eiO4kCY O9WnwxrnOSm3HCVgZTkBqc1m3+vM6zi6jCOtTcVGWdpf1cISTgcwl52ss+TaHFYe IypgFfhg8y1yl5P2NqzSfUMplEvLSsmcQ/q+2KnhfFRNLqvDws09lG3Imojm9cOE nzLEXjtAIm6ip318KcEK4zs= -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDhzCCAm+gAwIBAgIJAMXZAeV6XoKqMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmdvbGFuZy5vcmcwHhcNMTQxMTA0MTA0 NTQ1WhcNMjQwOTEyMTA0NTQ1WjBaMQswCQYDVQQGEwJGUjETMBEGA1UECAwKU29t ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD VQQDDApnb2xhbmcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA lvXJmIfOCKZ1iCRNqE6bhBZz0UM1wx3DyG0eb2/v56UgN80jTSgyZneTCb6DurHw VQ4dVtCCc/vLr5GfM6Kca7AGWPUHst3i3lHT6vIOz5dYGyf86EAtCdhedPcKtxv8 ERty5oAPzCc/IqCd9fzc/uALjswtBRCFfCquk9zJR754Qiv6dLPmMvTEP4jI7GeJ bZSEzhQfercDF+/h3Wt7qXorTafyW9g7ueg2+y4jKc15lk9xupumXjFiR3RRUzNT bjXq3pGKQSMP8qfMvWisErobbeel8PqFV8ucOZ1wAIc5gEv2OsKc/qOs1mLiWpJb lUdQa+TJFKY9ERdGX9r/1wIDAQABo1AwTjAdBgNVHQ4EFgQU4pdBPfs5FhCf5pAB xjyXIGdyfZswHwYDVR0jBBgwFoAU4pdBPfs5FhCf5pABxjyXIGdyfZswDAYDVR0T BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbcCgfKm9R9k7UrOK739uh0XsZnX7 zGwYpB7ruDultkZwrFinLf5mzZY1458NIozuiL/unBR4k7z9S5EUiWRSO9hce+Cb SCLW/XfX3LlthgcndtNTFuHTkPmjzYNnN03vIZQcg9PEljjpN1oQ0571MJ07GtVd CwVyUmunOK/rnyP8S9kOcpEYI2SQesZu7Ld/vO4nQIoy5eTgOdWbj3qCf1oXImcR 8nNZu7/vIrluaQS91AT7sbz/ii4vMNOKlTrlpAVFCcjVyk8kx44g8g0+PKoSmpUd Juoopd+AWgef39ASUmidHCWyoGTSPB3fVauC4TC6OOdkpx6r91oDpd3ZpA== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/golang.org.crt0000664000000000000000000000240513013560574017161 0ustar -----BEGIN CERTIFICATE----- MIIDhzCCAm+gAwIBAgIJAMXZAeV6XoKqMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmdvbGFuZy5vcmcwHhcNMTQxMTA0MTA0 NTQ1WhcNMjQwOTEyMTA0NTQ1WjBaMQswCQYDVQQGEwJGUjETMBEGA1UECAwKU29t ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD VQQDDApnb2xhbmcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA lvXJmIfOCKZ1iCRNqE6bhBZz0UM1wx3DyG0eb2/v56UgN80jTSgyZneTCb6DurHw VQ4dVtCCc/vLr5GfM6Kca7AGWPUHst3i3lHT6vIOz5dYGyf86EAtCdhedPcKtxv8 ERty5oAPzCc/IqCd9fzc/uALjswtBRCFfCquk9zJR754Qiv6dLPmMvTEP4jI7GeJ bZSEzhQfercDF+/h3Wt7qXorTafyW9g7ueg2+y4jKc15lk9xupumXjFiR3RRUzNT bjXq3pGKQSMP8qfMvWisErobbeel8PqFV8ucOZ1wAIc5gEv2OsKc/qOs1mLiWpJb lUdQa+TJFKY9ERdGX9r/1wIDAQABo1AwTjAdBgNVHQ4EFgQU4pdBPfs5FhCf5pAB xjyXIGdyfZswHwYDVR0jBBgwFoAU4pdBPfs5FhCf5pABxjyXIGdyfZswDAYDVR0T BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbcCgfKm9R9k7UrOK739uh0XsZnX7 zGwYpB7ruDultkZwrFinLf5mzZY1458NIozuiL/unBR4k7z9S5EUiWRSO9hce+Cb SCLW/XfX3LlthgcndtNTFuHTkPmjzYNnN03vIZQcg9PEljjpN1oQ0571MJ07GtVd CwVyUmunOK/rnyP8S9kOcpEYI2SQesZu7Ld/vO4nQIoy5eTgOdWbj3qCf1oXImcR 8nNZu7/vIrluaQS91AT7sbz/ii4vMNOKlTrlpAVFCcjVyk8kx44g8g0+PKoSmpUd Juoopd+AWgef39ASUmidHCWyoGTSPB3fVauC4TC6OOdkpx6r91oDpd3ZpA== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/static.rust-lang.org.crt0000664000000000000000000000243613013560574021120 0ustar -----BEGIN CERTIFICATE----- MIIDmzCCAoOgAwIBAgIJAIQvDYBQB/rZMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxHTAbBgNVBAMMFHN0YXRpYy5ydXN0LWxhbmcub3JnMB4X DTE2MDgyNTIxMjkwN1oXDTI2MDcwNDIxMjkwN1owZDELMAkGA1UEBhMCVVMxEzAR BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 IEx0ZDEdMBsGA1UEAwwUc3RhdGljLnJ1c3QtbGFuZy5vcmcwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCn/f5FjapuCy9oTmSMCA/gasS7xMbH3dfi3KMV a602XtcshQ0ivwIqIXo9ae0y/Ekc1Ih57gqXsQpqS2puHe1qo3xvw5ybB+GGhEh/ 9OxfwW+0QUwWTC7+YdaW9aNMHAB5gwk54b+V2faUSVZ+uK/onzzguhejDCJomvbU 2GyAF3AlK+ICiKvZRaPTakRbeeNAwPvRgcSrPy8Bg57TzW9XtskoU7i3nJ7K4a4U lK+2mwbJHjVMgGD1gC50ab8Wm4mZctkgPf66Yy2U2KM+jvy9+FlMA5V1VKbaZvvI +8Tg7Wuzr7kkUy+PwlxcTvVjSrHI06ZW5cimyo9ZUmVPQytPAgMBAAGjUDBOMB0G A1UdDgQWBBQvrGOQl9xNwJRhSIEvMAfuNDg0GDAfBgNVHSMEGDAWgBQvrGOQl9xN wJRhSIEvMAfuNDg0GDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBj P3izQX+KH9m342mXWrCMPntgQR6v7+u2kvd3Mtw7oJ324FLs9kqKNrLliSbmLSWl Jip/3DaYO5gUS20MlBl5Z4H+uLTYHZP5cq8zRo6xRtyv0Bwvw7+7zWg4Y+DyRg8E J5d0xQX9E0g3z6F/ACJRlEhHIjX5dJXX2oMaaBSc4ssRMIeaeJWPgB0IPEw0PYg+ xgS6+ZqDMVFxoBChNo/LHESQDejS2ybKefcImhs0GA/xt60tzPQEaP2VBlzxdNVu KRH8JVKrWymLvhW7R5A/GMnkkpjSVVd1m6O0SIsPQBREc7uAcQIWMe6rfK3JWoMl 3nxJzbWOriNLGNshXJmE -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/nodejs.org.pem0000664000000000000000000000565513013560574017177 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDYEyTuQVeZVXoo OIAgr8pcHUrTclQqrOLKvVVupkT76L+onu7+mwrn61t6SyS0G88d4lk6pd1wgI2j 6RnAz3+C8fhZDy7gsyD5lYK8/MtyeQN3WvWGDZ40Pmb4TdWRURL8ovcBxoE1p1+T +gBchPWdWO+XZlSWxFpjNvT1aGvn33ldNXD5me0OgeuCMAehg2oSupzT8Ju/YNrQ se1RhGBQUVRCYEo61sH6vZ/spg/yUIrGQhIPGur+N7e1glxQ9+ZoEUpxOYeBBr5Y cr4DOdkK2+kyJyb+h2HQr+aDyjS0APHsDnqVOx500jkMHwP3QSzZfgvMe6GFc8vE /yNRBuAtAgMBAAECggEAfpq5COFAcpei++4fJQfbih2fukVDC75BJInLhQnnYbL+ mc6GOqidu0YsU3u0BdRFhz0ZC0Qke8bXNzNd45uxGwise4Jp9T8AEz2HXTTCAFDn tweU1Pclu3bU3qi8emkGtwDFukSVcNqhJhNWIt/FCm0R9aP/7FcgnwGUhjapAzLa S5dY3Flo6sY9GFiBQ/LGs0/mYxegKr1LRfUlobcP7UafrPmBqArqbe70IcegY2dl z6qKxAF25/osB8ACFquDymZBS7ZIgwdUV3AIahVn5gz8x90yk9toehxS5foBDngS nWiDCEe71HeLFPIhYAMF918WWohYb1A9/qkI7JwAAQKBgQDsNRrV1liFlTFdPYCC W2/okye7yFfZLUuL3RuCO9NtIH+mo4Dk9YY9ob19hpzkpm18Og+iYkLKHYxYquCB qepgmh5sqlNAox/Jkehf+rbTCFlj3TnATHSPmRMTSqKKeIm6v3d//d8FemrwfqgT e8KHpPdh4zVZh7r0Gbq/EQF1DQKBgQDqLixIckfE4tBKOXLDYJv325VEi5wm0lBB RsjmqmgV7mODCV8Vr+W6J8O/TOQI4FCmEuonQhiWybqZDi28NUFmTGNtqDxUI1fd 9QSbuc5scKn391BsxMDs9CrRgFJ/glaRe/t0uCQtRSd/753UoMx43oTdlJcCEsjA 9NH+jyKPoQKBgQDEBVIO0YHG4cgEm8xw4dbeCHj54kndBjTijgyNKH7N2iF1Ncz6 tTLBJN9vM24yZlcHt9tPpAHPX3QgBTapBExn/J5xCWxrgLQZgEd6l0JvoUclk+qg RhKZNKxa3x5CkcOiwdA23ITfM/dZO5LaEGOgU+ukRXz5nqUse8m5VDCEZQKBgHST 0cWq5mF0C/63RJNQl7Q2osNBwNVuozcrtr1lnXU1fGJyGtyf+PvH6eFktKxahqt2 BQzQEY+XEwY4kbn8xPbZFjIzqvyzr302CTpAsCs5ltNzUZ0kAWq0TlCG0grZ5qB8 GPzM4m2K3JQKxAZimgedtoTcAKSulzO/bH6N4MWhAoGBAIyN+JHAwX3qhGVPBEe+ nML36BHlTbkTQseTWu58cAW5NHVEiKT4GK6+oc6LB5mJXksKDmSyTVnleLUNwniK 5YTYuhU/Uqr4PrkSna/OCJZ7vFW1qOmkKJZAZKaApb6SMuExtHEMcqtIKKGzPQAu 26+W0MZLftCuGuGh4UfX7q3I -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDhzCCAm+gAwIBAgIJAM0RuxL089KdMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCm5vZGVqcy5vcmcwHhcNMTYwMTE3MjM1 MzQ2WhcNMjUxMTI1MjM1MzQ2WjBaMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD VQQDDApub2RlanMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 2BMk7kFXmVV6KDiAIK/KXB1K03JUKqziyr1VbqZE++i/qJ7u/psK5+tbeksktBvP HeJZOqXdcICNo+kZwM9/gvH4WQ8u4LMg+ZWCvPzLcnkDd1r1hg2eND5m+E3VkVES /KL3AcaBNadfk/oAXIT1nVjvl2ZUlsRaYzb09Whr5995XTVw+ZntDoHrgjAHoYNq Erqc0/Cbv2Da0LHtUYRgUFFUQmBKOtbB+r2f7KYP8lCKxkISDxrq/je3tYJcUPfm aBFKcTmHgQa+WHK+AznZCtvpMicm/odh0K/mg8o0tADx7A56lTsedNI5DB8D90Es 2X4LzHuhhXPLxP8jUQbgLQIDAQABo1AwTjAdBgNVHQ4EFgQU44gu/w7Juo2HIvWV pGfZbgnY15MwHwYDVR0jBBgwFoAU44gu/w7Juo2HIvWVpGfZbgnY15MwDAYDVR0T BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVZItQ973u+yzHF1zQXGmhDIRQrcZ 5r4zmnT0VJhcZiPh3kDJfX9YnSLY2zYWB34UHhrO8Zp+55dv8e99y0RYgtQQgt+b K8D4U2NP1qBDAiFkOhKdVgXLL7r+MjZpGFTr75GDvFZQDyP+T1GUw++XSVVYQhFP x4RwSwMmUNv80uHMRrcPYe6a8XKCa1li/OlBJQq/JpFyhITDuo4aMVRcPK0HAfJE M+ZMM9mmHrrCqazFo0qThbJCz0hRqKZGMphjJ4kdPt3Y8536fZsEzTcR6PhLCOvd 4AovC7EmDmY9o2FXpPDmt8GpxenMdRRZkV+DkBv8OGcpsSLJ2vhflVm2MA== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/data.services.jetbrains.com.crt0000664000000000000000000000246213013560574022417 0ustar -----BEGIN CERTIFICATE----- MIIDqTCCApGgAwIBAgIJAPoNW2O3W47oMA0GCSqGSIb3DQEBCwUAMGsxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxJDAiBgNVBAMMG2RhdGEuc2VydmljZXMuamV0YnJhaW5z LmNvbTAeFw0xNTEyMTEwODUyNTFaFw0yNTEwMTkwODUyNTFaMGsxCzAJBgNVBAYT AkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn aXRzIFB0eSBMdGQxJDAiBgNVBAMMG2RhdGEuc2VydmljZXMuamV0YnJhaW5zLmNv bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMpKcWEr0NKZ20zZOMbk o2ZbQZZ2soAmwvHb9Nna5CHO3kzOP2A+6zQZvhdwEc8W3LtOgZgK66XKhvLTQ1lW p9fEBbmJtJEUAutoNDh5mip75SVLklL0AEq3M1KVZKPx20KGrwcnZnfLFJSH3RC5 r0Zb/Ptu9sRMjDbvg4iMIch+VrNa1P34EUdMHWUQAbl/mgNm19vJ24ZvOUj4zX9M 6nDTJGmigmXBtbhkqAayueQ+dULUx8bM+btKCRU1ChadqZdjaB59rEq0EMDruLW5 SA8DSkM2KwrRbNtxvqfPKsXDKZYYWPTmK4GzlFgb2WZbifMws2c0TAqN01KX/RDy BU0CAwEAAaNQME4wHQYDVR0OBBYEFMlFjpvuzTPurQ5jYRlAQbQdmkEBMB8GA1Ud IwQYMBaAFMlFjpvuzTPurQ5jYRlAQbQdmkEBMAwGA1UdEwQFMAMBAf8wDQYJKoZI hvcNAQELBQADggEBACqrK0PtcYKLppXmaAqv5xFghcvyH4OKSb3g+OS35CEwofNP +8dlFoCLcVCgLRcOzY3E49ky02dVmpjOg6GnK6A69gwzsw0WRRx8LzZB/hoT2fvi SDe+Z5cQ71xB9MyfUu44UQ4q8babtHwgPqcBgqT9ofp0qW0ofE2tnVzRMcc79gQE NpYnEBRn1R9k4kfRgJKk+9WuY0woNG9W+z2+ERcDit2hQeXsyLvgx58RF3tGEar9 m3sy2pBSjBaO/W5wq3P+bIIEyjqG1gWhAePG2j18hvu7/njP70oFhis2zOJRnkos oGBEZhjNDMRiW5qj1kjUgfxRqH/4U7taSYVzenA= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/multipledefaultsframeworks/0000775000000000000000000000000013013560574022075 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/multipledefaultsframeworks/__init__.py0000664000000000000000000000000013013560574024174 0ustar ubuntu-make-16.11.1ubuntu1/tests/data/multipledefaultsframeworks/twodefaultscategory.py0000664000000000000000000000334313013560574026551 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Framework with two defaults frameworks""" import umake.frameworks class ACategory(umake.frameworks.BaseCategory): def __init__(self): super().__init__(name="Category A", description="Category A description") class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() class FrameworkB(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework B", description="Description for framework B", is_category_default=True, category=category) def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/multipledefaultsframeworks/defaultframeworkformain.py0000664000000000000000000000234213013560574027366 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Try to get a reject to set a framework as default for main category""" import umake.frameworks class FrameworkA(umake.frameworks.BaseFramework): def __init__(self, category): super().__init__(name="Framework A", description="Description for framework A", is_category_default=True, category=category, install_path_dir="custom/frameworka") def setup(self, install_path=None, auto_accept_license=False): super().setup() def remove(self): super().remove() ubuntu-make-16.11.1ubuntu1/tests/data/apt/0000775000000000000000000000000013013560574015175 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/apt/create_package_list.sh0000775000000000000000000000142413013560574021506 0ustar #/bin/sh # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA dpkg-scanpackages . /dev/null > Packages apt-ftparchive release . > Release ubuntu-make-16.11.1ubuntu1/tests/data/apt/Packages0000664000000000000000000000463313013560574016644 0ustar Package: testpackage Version: 0.0.1 Architecture: all Maintainer: Didier Roche Installed-Size: 26 Filename: ./testpackage_0.0.1_all.deb Size: 1698 MD5sum: 09c049be56996d2856d63a1fff8bc5fe SHA1: c51ac45e9a9d5f6dcc78de7db33d766d24f80b4f SHA256: a51e9128ccc800f6ab36bf25d7ced128cbbadfffb34d243198795913fd72e7c4 Section: misc Priority: extra Description: Dummy package for testing Package used for testing debs installation Package: testpackage0 Source: testpackage Version: 0.0.1 Architecture: all Maintainer: Didier Roche Installed-Size: 26 Filename: ./testpackage0_0.0.1_all.deb Size: 1714 MD5sum: 6805bc475b48d82af3766f82c36e14aa SHA1: 8e6f1924aff2086afc2bbc9c9aa6ac8c9464fb04 SHA256: 152d328d7bd757bc11f2e5f0dd496768c745038946151cb5c5191e17f08e66ff Section: misc Priority: extra Description: Dummy package for testinga - other Package used for other testing debs installation Package: testpackage1 Source: testpackage Version: 0.0.1 Architecture: all Maintainer: Didier Roche Installed-Size: 26 Depends: testpackage Filename: ./testpackage1_0.0.1_all.deb Size: 1722 MD5sum: a7e3f78b1371a282c39ea3b4748ec983 SHA1: cb64e24b8cd567160cd2e912f8cd878e13b6d6cc SHA256: 26ba2636e06ef1a8d637f5b37dfdf2d14be7971a20ccbae09481e63bb158cf7e Section: misc Priority: extra Description: Dummy package for testing - dep Package used for testing debs installation with dep Package: testpackage2 Source: testpackage Version: 0.0.1 Architecture: all Maintainer: Didier Roche Installed-Size: 26 Conflicts: testpackage (<< 0.2) Filename: ./testpackage2_0.0.1_all.deb Size: 1732 MD5sum: f141d37818d53249b0468982a3f9d3e6 SHA1: d8474882876dd15c69e8a904612440782379f17d SHA256: 51d581dd1f6502c179fae4c5e00440906b13ab01d6e7a5462da6b324f62a5241 Section: misc Priority: extra Description: Dummy package for testing - breaks Package used for testing debs installation with break Package: testpackagefoo Source: testpackage Version: 0.0.1 Architecture: foo Maintainer: Didier Roche Installed-Size: 26 Filename: ./testpackagefoo_0.0.1_foo.deb Size: 1726 MD5sum: 394ae0f62d30e74d81efda4d90a9fea5 SHA1: e2cc8783b86694b576ec8d268919c81f1bef06e1 SHA256: a78ff29d30d85b2acd83ee0cae2d0961eb5e685cc77f921f61cb928140c7b559 Section: misc Priority: extra Multi-Arch: foreign Description: Dummy package for testing - only available on foo Package used for testing debs installation ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage0_0.0.1_all.deb0000664000000000000000000000326213013560574021573 0ustar ! debian-binary 1404741350 0 0 100644 4 ` 2.0 control.tar.gz 1404741350 0 0 100644 426 ` Qk0`?WԖeK-eebVdX8uOI)F|eȮ%!1{\K^ )xU2o6gTd7X7o)Y^Aŧ@5仲sL-YcN@kO~9.vWmN~sJ%٧t+&4yyO[ WdA{{Di:їу^+zG]m.P{م:gų!B!B!B!g1(data.tar.xz 1404741350 0 0 100644 1096 ` 7zXZi"6!t/' ] }J>y&Tao4=&T!}^"C2*A}a s`2|#L]<)Wh4n(Ʀ @"_RZV{2W I$ v i|e~?2ϐG5Ń_o̭ٙI/fv-7; W "*/ jhMw_5}2ZlȴGǭ.Ûb'7iH~n~K AF}A 5/o1w6Lqw<{g.t8R^j v*N!׼NL 6Q^:^H_L53҇jF`.jpG܆l%!eK T)c,ur̖Dw([%e TKϿG7Ej@f1۝Ȁl}^L=jEXa=>B#!$8=$@0 YZubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage2_0.0.1_all.deb0000664000000000000000000000330413013560574021572 0ustar ! debian-binary 1404741350 0 0 100644 4 ` 2.0 control.tar.gz 1404741350 0 0 100644 443 ` Ao0`>n1` MeI"n8M6i'!cx6Xi\:t/Rx90>HDd[UZ0sYi^dGg!ݶR_#ũA7v^Q4'L8!^VtcGY5]kU{q9,e~AmCLlhT3wu'8i ;c I9#64 ;N;9{Oo >0a8B!B!B!BW~( data.tar.xz 1404741350 0 0 100644 1096 ` 7zXZi"6!t/' ] }J>y&Tao4=&T!}^"C2*A}a s`2|#L]<)Wh4n(Ʀ @"_RZV{2W I$c׾ xtVZ&k:X}3,\8Wp,:;:_X5a!qp\۵*<f/a͏^ew[ f71A$[ q<ƢU\dqӚ h f&\7qPu{C%q?ZP̢uW"OI$'8A5f2R4zu[Y)*cKO˥IɈ03z8*XI D:@`4hYI'xk9\ҀH,"eK~mg.I#!<*W8]ֵa_q0q).@#2 )0~eh"2U  6= Xg v׌ $SF̏=oU/$9xDߧ#175}NIc>2~x0&O'4?}-E1odA|G IGk3FȡqAiz~59j( bY%~р|99*kfed u\,O C#j6u^chL"#p0{My']㔵j.B+Kzǔ1ƫ%RIfK -EuYѵN /"ys~!cKkUyqLڲ8<\ki+{"嘯^wVьRRt s#ƳU2:L^)crz1[3g_Ƀu&]d2G4q,9-E-[%}ByAM:E#82x(֐FGK٬iu0PdH>0 YZubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackagefoo_0.0.1_foo.deb0000664000000000000000000000327613013560574022237 0ustar ! debian-binary 1404741350 0 0 100644 4 ` 2.0 control.tar.gz 1404741350 0 0 100644 442 ` ͊0`zObRv!z-ֶ~JO_K=%|`lheyrsEel}GwYQYEicv[U a%$*'\܍ϟϿeU )orZox)yUY!-B\{p$hL.10>_VrZZYS EŋBb˛(9&~/?kVJ {xߎ\cz0Xͼ#EVdeh=HlLzz#{4X5=.>dL_osq9![jHfYwYςtNZ}ڇi:|!kzɆy<SQt#2yۀx5sD_RKxB!B!B!B~2(data.tar.xz 1404741350 0 0 100644 1092 ` 7zXZi"6!t/'] }J>y&Tao4=&T!}^"C2*A}a s`2|#L]<)Wh4n(Ʀ @"_RZV{2W I%8Hhű8Pp%d6cڣs^ׂ B  k4Ɉ)HLIuLsrT|]tg2}ߡ%{_FSV0Q%cBNZKql`]ŵLY#%~8PX. NStmQASh]n\@T(ˋ/繉KT_8@x>h7˚Xn$>)&8rgCRy]v?g> JgNl!'6c<+-D4+iMlTg#^D& 4xCrJLtGaQtyn*#Ps0P[i: 7*J aV[I <$` rxmgRPr< W>,A[~x(-!%גDWg"DQbndO#Gih dg @vEڀYo 7 rMRsn"tɴU$UnM1I7oHC΁çr0c.iԭ8,!0=H e}ɞPyk>0 YZubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage_0.0.1_all.deb0000664000000000000000000000324213013560574021511 0ustar ! debian-binary 1404741350 0 0 100644 4 ` 2.0 control.tar.gz 1404741350 0 0 100644 410 ` A ~&FIRZK }&qPug0-t{)-$ScY+y~5RI.D张-&(-uGbeܖxmyM?ߜPFCW+i[ UtzS%͓2^GXϤ7J0-lo! 1[Vu]f!<7N7~M1BW/\`#!:(+YYOL.I[ k ݣ{%"yECӎ4C4/+۲Y:zk{=C- ˶ YB!B!B!B~j}(data.tar.xz 1404741350 0 0 100644 1096 ` 7zXZi"6!t/' ] }J>y&Tao4=&T!}^"C2*A}a s`2|#L]<)Wh4n(Ʀ @"_RZV{2W I|#@_f;:g\C1zSøv1L2Hˆ[ gI%b d>)̺ EOqVaӷ8kT6p1Udگ-ӟ,faTײZ'{Iu KoGp5s';K3 n-N_}>"K)S*֖ uw+5w*7_w-J] 6mWg=A_S)2S557p}c砡vboRhe<̼$حGIާ+ˬ\&D\j&}C0ĉPc߁HQ?Ŗ7^/_̌9{'Rr.>f \d LY8 bv7Y jX37xp(Pfd2(υN>Pw}귝yʋuة@H)-%$*P a,.^0n7h]oDžD\L2\[oA uցRUb,bRyZnF ?sw4&U`A\Š{~GS0M]ʓ:0p'; CõGT%Q~DdW# HT]<~0E[D{ɽrDEQ x02f߽,Ʒ3{Up]ϯjDy}Um3ѭoq Ji'!tnZ{֩˧#On4 <=k nzY #i {.-tRNh.ä@d&lfQ_=rus'K0T&ZTO]wKZmEPr&>0 YZubuntu-make-16.11.1ubuntu1/tests/data/apt/states/0000775000000000000000000000000013013560574016500 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/apt/states/testpackage_installed_dpkg_status0000664000000000000000000000040713013560574025366 0ustar Package: testpackage Status: install ok installed Priority: extra Section: misc Installed-Size: 26 Maintainer: Didier Roche Architecture: all Version: 0.0.0 Description: Dummy package for testing Package used for testing debs installation ubuntu-make-16.11.1ubuntu1/tests/data/apt/Release0000664000000000000000000000145613013560574016506 0ustar Date: Fri, 18 Nov 2016 09:37:28 UTC MD5Sum: e57e979a05a98a765bc79d198d028728 2459 Packages 89912e52654745f45d83cbe17fdca2f4 36 Release SHA1: 026f6908ec1b0da0bf74ce734d2569206953c45d 2459 Packages 678f76f2a915115cebd94106ee9ed16997e70394 36 Release SHA256: 1a565bd9d62220c369bbf941a99813da613c1fcb093c67ba3a6a6b7b13bb0874 2459 Packages 375f7cda62470aea285cc1282da9c3b6267f50768a0d40c01c60f297b16db44e 36 Release SHA512: 402520dfe426361f9acd100b957f04ce14bd5ddd0b28995a6e1d3c1e39f26772211c8edb2da70c4cc825244909ef5cc6b5a7a73a59eff01bf63db1d6ee3db353 2459 Packages c00ba55fb8ff2fa8b69aa89c50a3e433c33c614fbefab4154cf4c068218b29da8ff1ab26e4db5164554808103743ff8e19c713b8dd06340236916500f949c7ab 36 Release ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/0000775000000000000000000000000013013560574017470 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/0000775000000000000000000000000013013560574020712 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/source/0000775000000000000000000000000013013560574022212 5ustar ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/source/format0000664000000000000000000000001513013560574023421 0ustar 3.0 (native) ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/copyright0000664000000000000000000000170413013560574022647 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: testpackage Source: www.example.com Files: * Copyright: 2014 Didier Roche License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package 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 . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/changelog0000664000000000000000000000042113013560574022561 0ustar testpackage (0.0.1) trusty; urgency=low * Initial release * Note: to add foo architecture, add it to: /usr/share/dpkg/cputable (copying your current arch line). And then: $ debuild -afoo -- Didier Roche Wed, 11 Jun 2014 14:00:13 +0200 ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/control0000664000000000000000000000262413013560574022321 0ustar Source: testpackage Section: misc Priority: extra Maintainer: Didier Roche Build-Depends: debhelper (>= 9.0.0) Standards-Version: 3.9.5 Package: testpackage Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, Description: Dummy package for testing Package used for testing debs installation Package: testpackage0 Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, Description: Dummy package for testinga - other Package used for other testing debs installation Package: testpackage1 Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, testpackage, Description: Dummy package for testing - dep Package used for testing debs installation with dep Package: testpackage2 Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, Conflicts: testpackage (<< 0.2), Description: Dummy package for testing - breaks Package used for testing debs installation with break Package: testpackagefoo Architecture: foo Multi-Arch: foreign Depends: ${shlibs:Depends}, ${misc:Depends}, Description: Dummy package for testing - only available on foo Package used for testing debs installation Package: testpackagearmhf Architecture: armhf Multi-Arch: foreign Depends: ${shlibs:Depends}, ${misc:Depends}, Description: Dummy package for testing - only available on armhf Package used for testing debs installation ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/rules0000775000000000000000000000006213013560574021770 0ustar #!/usr/bin/make -f # -*- makefile -*- %: dh $@ ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage/debian/compat0000664000000000000000000000000213013560574022110 0ustar 9 ubuntu-make-16.11.1ubuntu1/tests/data/apt/testpackage1_0.0.1_all.deb0000664000000000000000000000327213013560574021575 0ustar ! debian-binary 1404741350 0 0 100644 4 ` 2.0 control.tar.gz 1404741350 0 0 100644 433 ` j0`zGRJ {,"e$vzsv|`ll4K.6}}.XgeYؿ0Pt&Ѽl/rEU1/N+MـhD[á.cKcŻA0K$;(2˩viL%\rݨ,!okEBnD]Gљ$Ae_UMSsnr${8uIyc-<-wz@ʼnrOi/p[3ڀV@hUO.SXReǯ0ۛ &/=}Gw:[ qWeu!=X2SG暴ׯ'q F2_B!B!B!B( data.tar.xz 1404741350 0 0 100644 1096 ` 7zXZi"6!t/' ] }J>y&Tao4=&T!}^"C2*A}a s`2|#L]<)Wh4n(Ʀ @"_RZV{2W I$+ vy+ J#אaרzQ>T?VP&񇺣1%<3Xni58BxvAla뤤REpaL+RY0aEs9v:Pu!cm{cN:TM-P|Щ ,?HGm #pXna M*TË=ՉH/R_L$j Չd_PLH< z#[ DmVlh<[WwnqRIe5!4ǯ'k]l=50 \roP =>1DUuHnFxv$oH+XzJ;PIy=>~Od$q+Vj|an)!A\7N.J0KJT[l[Hw7f{["̅#Y 5*E**ls[VɦcI"aJPoTM>0 YZubuntu-make-16.11.1ubuntu1/tests/data/code.visualstudio.com.pem0000664000000000000000000000602713013560574021342 0ustar -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSiDmIjpkJEwAH Kq8DsV2wX13D5ld745XZ3pT/o3Jonge7EuJHYzTwATNYkERRhJ6QTR+1VP6Gq+gV 1g0tdB0pCtXGzj6McYDoQi8y/h1PaldxL5xb9vpCHUfKO0GjyPCpZe7p/lMGJnC0 yJJ6EM5AhLfj6gnQFhaei0pVgeLuA7CmI5aOmNY8mzqdj5mbktrlJhJG0jLUuh0y XW8IxgYOQAECeke5pis9sXhF0qYmEsyABrRHi9NKj/LPMuKzLiRWkO4/znmmzc3D NRwGD69iEokasXoohe9jaUcMdwY+/oHGJXonSxQ5P05MocGbmTYicD+R2Ft/Lyag eZlzrBj5AgMBAAECggEBAML2+mi2vYwEt2rroUXHNB8IQdoP7wZA3V303YDbyTCO 4FPjCf/YJIb6ZaVnfI0NRpYVhf60Jj1q5zOJlYx5UiPW79/60TvYROtRl0oev9/y d+XOlHsp/dnKKdhjBcd6ZzxItHanWhWA9bDFabh25boj7fO3oby9J9dM4NrMvO1y eMW2XHYjm8l+s8mqYyv0PD2milBCH7ofii/wSf2iH9sKf0Mix7BUsVSEueVIc0dV WvQ9x+GJuFl8Czdk14r20LQRQP/JcAFTymPwp0r0ZeKjlPQk71p+DK+eho8QpDXv 680LmBXTTX7wf2SqVetydsIPaUkoAG122y+XdsOwoR0CgYEA9NQea2eKPwKz7W3w d4Fe//yUDdEI0tc/muUHylg/UUvCjvZ86sU9E/qGzqBU2j1ioRf/hIP0pp1zIcZ9 HjXlS4r6unIwuqmH3hQSFxnXCZsMHLqPTNaB383rzBPlNMXrrv/QLr6ZzLkEd66h PzkmeeKgJMSDcB4fH+2mXf06hP8CgYEA3CN7ywqTf7BWQdM9kuAvbOA7bbxqqpGy Y5AXm7JpRBgJG/2uiDCN+9O4ZaruZ4paJzCiDrFf0RnE1BcdU3qsC4fqhqAL3UWh kjqzU9YdltY5oOEUuB+KX1uavHvcaOZeLBJiNsoHCBxGGWfdLRdtiJi4l3Pfj7OF VBX+bZ+figcCgYBTX8EUNmhf2N3JJz1SlR3y8uLAacUld+PTLdefUroNR010PgCA Orb4DMLHrtX2lBz4WyHK0N0JuGiywdNt7FCvjx6fS6/IgV8hg5g9gbE3NjPDvMx8 EDieLJP2JXhSpmwCZl9Q69uYWhFpaHDFBQNTUpfSrZFNJxTWXKnhLBE3pQKBgEaQ 2U3sxftYe03+eO5sDsfH2UUD8O1cZuKjfe3a8wNw8PqYByqA5gKji6iLcoCeSOfn Hwu2sBBHQmD6R9xKpnvLxdIB28vCVliZmIJ3UGTZpv97JzkeYyzOIHvq+Gxn7CgU fIczm61t4sqiELQznlj7G7Dw4+kcktCxfC2HzYxhAoGAcVdRQyuuJEXt8H7Mrzim ZZB2JRF+pfvOMZM77iYWmqmYHQKS01a5aogIBlyzuWpG4M9AHmtZkxrnnUjd1aW/ 5etGiuPPwX7G1wEm94WPFU9RSbjh5KyQVa4Pi6u649JgFYCWLDbI3yEw6JQ0aH0w nG2V4ze93qjRrzUA0zwzkH8= -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIID1zCCAr+gAwIBAgIJALcOyQpcVt+2MA0GCSqGSIb3DQEBCwUAMIGBMQswCQYD VQQGEwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTE9MDsGA1UECgw0TW9jayBjZXJ0 aWZpY2F0ZSBmb3IgVmlzdWFsIFN0dWRpbyBDb2RlIG1lZGl1bSB0ZXN0czEeMBwG A1UEAwwVY29kZS52aXN1YWxzdHVkaW8uY29tMB4XDTE1MDQzMDA3NDUxMloXDTI1 MDMwODA3NDUxMlowgYExCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRl MT0wOwYDVQQKDDRNb2NrIGNlcnRpZmljYXRlIGZvciBWaXN1YWwgU3R1ZGlvIENv ZGUgbWVkaXVtIHRlc3RzMR4wHAYDVQQDDBVjb2RlLnZpc3VhbHN0dWRpby5jb20w ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSiDmIjpkJEwAHKq8DsV2w X13D5ld745XZ3pT/o3Jonge7EuJHYzTwATNYkERRhJ6QTR+1VP6Gq+gV1g0tdB0p CtXGzj6McYDoQi8y/h1PaldxL5xb9vpCHUfKO0GjyPCpZe7p/lMGJnC0yJJ6EM5A hLfj6gnQFhaei0pVgeLuA7CmI5aOmNY8mzqdj5mbktrlJhJG0jLUuh0yXW8IxgYO QAECeke5pis9sXhF0qYmEsyABrRHi9NKj/LPMuKzLiRWkO4/znmmzc3DNRwGD69i EokasXoohe9jaUcMdwY+/oHGJXonSxQ5P05MocGbmTYicD+R2Ft/LyageZlzrBj5 AgMBAAGjUDBOMB0GA1UdDgQWBBQmVWhkaDF6PHbXnDGNICP8aACkNzAfBgNVHSME GDAWgBQmVWhkaDF6PHbXnDGNICP8aACkNzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 DQEBCwUAA4IBAQAHmQQXMs09tDQjvPdO9i82JZ/BduBFI0FuZV/GQs2zcfF3EmLC USwXttKT7pUtL0HuO40wfwHuTl9P+bNsacpeAMG80ND437b7+o34BfAd4EqzP6mO JSZ0wCqsNvRI7H7BpsXjdO5H3DZgv6Sqcr6ibwWpRyspl70NnTzM/sjvARMrzX21 2feKEhS/MsuE0phNh9WKipGymqALFgwuVw5a+E5TSs8X/9is+YW7fpQ1y2Hrf/3T NQF4FQ41730cHEiaO/5WK6wypi55p62hyEdjlgvfdOLdxw20mu76BtX6m4S5+a5C bGBvmiSFeRyk0EXCTDYc/LYOe3WW/qWdQsnb -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/api.dartlang.org.crt0000664000000000000000000000242613013560574020261 0ustar -----BEGIN CERTIFICATE----- MIIDkzCCAnugAwIBAgIJALSb3qXZ19zRMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxGTAXBgNVBAMMEGFwaS5kYXJ0bGFuZy5vcmcwHhcNMTUw OTMwMTQyMTE4WhcNMjUwODA4MTQyMTE4WjBgMQswCQYDVQQGEwJGUjETMBEGA1UE CAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk MRkwFwYDVQQDDBBhcGkuZGFydGxhbmcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAv6jtbTZmb+xQa1jbFuXPdNNW6k3S0WDVEFlu4RBGM1RYJ1u+ XtC9vEKJMCzQqUDnEObTB/hYTll79x9+ZOnUzwiHFTM8MhQMo4h0ShXnncOBae4X 1zVi6d+SRrGPjXCOJi3ghdnsnoFMz/QW6v0CfsDgiq0/siQ2sXYoaxNIRbtlWmyH Cr2LfYXm//+L9fQSOvCXsfgHv10XSysHS9u2+fq4he463hmpxIKPtZ1f94sq2yg5 va2xYfceaF7jen0uxBcQMwJqO+lIN9WCsrpmWLTERzVzuN/H0DK8xjCfgSlhrz5w AhIZ0ZG0SXMr+XnMMC9UN0lstj+F0tE5MKSMbwIDAQABo1AwTjAdBgNVHQ4EFgQU INl38sv3/6yjLDjbyjR5slQNa0IwHwYDVR0jBBgwFoAUINl38sv3/6yjLDjbyjR5 slQNa0IwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYvDi9QURcC6i 4zHdnYSklEQSrIrbiqfVUKokol5fa8ohdwI53mYRviwrAMJT5NOVWW0ZGLI+o2H7 4HtGV+BX4++2UmvoK2DgPSg70hGJRsHJhDwhkjo27Gtkdn4xE6Fr9JfVIWQ2NCoW lJ2a6ZN6gzEtTMz2CT8M1AoXteI0tCwDS9azrcIjmNPMeKB3TxHU3D1Hdaos6Ahy LUUhNt5ETwA5ua4nZnkmeBCFk9S4lexnrH2J+qBi9YJLsPvbGiGcH+nJCXCKAHou D12o6JFY+Oxm2ccH3obX+yr2VMbN9vNU6s0/EzXTBYUkh6a116XAvJIp4sURAB42 8NvYomFOig== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/netbeans.org.crt0000664000000000000000000000241113013560574017506 0ustar -----BEGIN CERTIFICATE----- MIIDizCCAnOgAwIBAgIJAKV0wmMGmeB5MA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxFTATBgNVBAMMDG5ldGJlYW5zLm9yZzAeFw0xNTExMDIx NjAzMjFaFw0yNTA5MTAxNjAzMjFaMFwxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApT b21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFTAT BgNVBAMMDG5ldGJlYW5zLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBALnF19MaByOa44WkHygDR3TtyIiusMI0JFGC/u049MczUU9TWAul3CEePRit h4UmlzIP9JeBEfhsAkqLNH6t+70fa8qwDMOPdfZKaO1q3ZlR3jPhPKRhEHl9fNo7 5miLC3XYVUNiJZV2VZxKRT2ID8KndNhSD5uogGAaHiTU8jGAw5BkYMWLQqkZpbuk vvloZOLIgWhrBzw2bBVw5PNuoC+0WtMqf/uImeSsD7xf580eOwPHZp1R8dTdlqfx uOFVkpu6cX9G1d9JZeisaH1w57jh6uW0oRStHuXz1/2c4vjU2PaJM+zRN9sFrvr2 Oa02yQ2iawV6DSzVV3XwBuTdDHsCAwEAAaNQME4wHQYDVR0OBBYEFKBhmoDTcTWo KOIpL/UXSM6XE/pMMB8GA1UdIwQYMBaAFKBhmoDTcTWoKOIpL/UXSM6XE/pMMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAAzj+bVvCKYm19ig8uqDW5g p4Eq/R06LpV0J35iwKRN/YN5lyuIIdAFUtKLDgYxXaqUeh68zDcMyBpOU1o66Ei5 h8OT6quVA8IFmPHGWCt2KCMt58a2GFC92RHtHUFD91xuu2zFakXhZYxJvVPt1xpV QBOixTsW9O/pCO8KQ4Id9RXAgcMHMb9Ngho63cb7+FvSCcHd9/BJ/drO6PbcxqcG fLvHvdlTDV5aL38N0b2N1Ufpnu+btviQnuIiBCB1WWU/7nxE7phl6xVwVmLUCGze U2frDvRtahVe89R+GBz9QiNK+5i7wiz559vBPDFYneG0LVa+FA1scBpFEXwZ/4o= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/community.unity.com.pem0000664000000000000000000000570613013560574021074 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDq+8BS+1ORU7BV p2JwP5iBOI5+Z4RHdWDbnetcSskSv9CD8DGGdVojPQQHrjcM1mc8DfMb5e1az4Kx B/E9OppHH8jTU9zvD5cCxCZIiariCz6yG1jLDPFOplfUIiP2KY7cAg2I6J8J9Ven vkyWpdCrNwuZqV07YbbRZzQ8KquvuLpj35yNW/hQFlRzwaijpvkCKH/w5HumOx+q mbbMYu9NcpHj2fAjgSvNb7UOfDqIJjT3hSQC1A4nirU+85k4LAYAMrdI27CjTNFQ U2EWrMxsN5zRhbltGMUaZRg0YcQ99EuVXRjzxgJC/uIyptjWl2K9Kh8Wp4TJ8uGh 0yDFlZmNAgMBAAECggEBANXNxoo6XykFypXEvQ6A7tP0j8J3kaYrKLvqjjHlYdqL aMADlixPLnqNk9MhMrmdg0TjNGYX6MUNtk45echKQAGi6+lMjuN9fdtoeaTajf8q WBtaQopN9mmndJZxkeLyoSeRPptpfPtkniLkRW90485FQWrI7SmQmPUjQCXWdWxl m+o2QhePhVJjA4gld4SLFp28iyRqfi//OoQXj+UfjfiY/IRPdo+qOqIdvtkODWtT lZfYpx11zCG0IwX5Xh/fMLuPYPGQF/023NSNFHKIAs4N6PCiEC60ooRvUULcQluq 43KZFXawjCdVyH5OJr85eIu4CvzCZTny+WV6xtGk6wECgYEA91/6xy2Ef4l3VU3X 6sQKhpj0hpdfy8jcnr+TbPEDO79sovwsVdpNcCW0Jgug5v5eKKZdsjPbsaRc1+wz MzbJzaEhfsIkcj7yZx/ogcXQjnXsncAZaQLDnjzuUsemCpUDRyLq/kqVAkweJqoS vPeKb98ywuv2ibP4BVInRUmEHi0CgYEA8y0q2nMcaEGZ2GJ3wp8kiNWz8LDKdN3E QeXNw9tBiHfZasp3uoXIky/DdDFY/Am/QHbE/6uo0d8yexiAI2emNCtgm38LNf0v cugfEX7qSJDcMdhR7MtEq2PHpY08BCeioxJ94l7GKDnXsSKYtOPd1jWjZEkzd3K1 /io8AKlT5OECgYAJ+uFPL9LsoksiMeXIHuidzYXv+CNxQUVFUk1MU9zhiDOFz86q GAiPwbWm40k2iISb9zpIejcez5a/T1QxeMBjf2CukH6P7WIyLuNeePCVDsThCGL+ DZJ+y86BoHRecOyU7h+06qVgVlnRDYN8BDCdms+ddY+Ytp4G+O2EqhaecQKBgQCt vsLUi9RrJRvvwAMDWkN3RQEo4pf0whKcZr4KxxhekgsUww6ihT3W9BR5a1zBz5EH VRTR++tF8GwYCVxcb40Pz0JaN35iF8EUH4c7L+vi5yV8s6ttPZqVvlgCEBQmf88z Jl4tJDv+t71FgYuMCxcQGwjf+XE9Ugd4TuLKMjGP4QKBgGtRXHkJ5U1gEI1urZsY XXa/lI8MlBVQ2XvkxTwpeAc7Jnr0RxMGd8Sky+Izamzxhd2jgY3f3ElKhi7svvVg 7jKlXYnBvEVSv2WicMtfjQa1Mu/E1+W6VKkBP+ycQ/F0wHdA1yuMazpYiX/qsRiF c5/j2UVyWH5YSl0V+yE5PpWT -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDmTCCAoGgAwIBAgIJAO43IwlPESOWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxHDAaBgNVBAMME2NvbW11bml0eS51bml0eS5jb20wHhcN MTYwNzA4MTQ0MTM1WhcNMjYwNTE3MTQ0MTM1WjBjMQswCQYDVQQGEwJBVTETMBEG A1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg THRkMRwwGgYDVQQDDBNjb21tdW5pdHkudW5pdHkuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA6vvAUvtTkVOwVadicD+YgTiOfmeER3Vg253rXErJ Er/Qg/AxhnVaIz0EB643DNZnPA3zG+XtWs+CsQfxPTqaRx/I01Pc7w+XAsQmSImq 4gs+shtYywzxTqZX1CIj9imO3AINiOifCfVXp75MlqXQqzcLmaldO2G20Wc0PCqr r7i6Y9+cjVv4UBZUc8Goo6b5Aih/8OR7pjsfqpm2zGLvTXKR49nwI4ErzW+1Dnw6 iCY094UkAtQOJ4q1PvOZOCwGADK3SNuwo0zRUFNhFqzMbDec0YW5bRjFGmUYNGHE PfRLlV0Y88YCQv7iMqbY1pdivSofFqeEyfLhodMgxZWZjQIDAQABo1AwTjAdBgNV HQ4EFgQUo4DDPR/7sDyPoGK+tFAB6Ib83akwHwYDVR0jBBgwFoAUo4DDPR/7sDyP oGK+tFAB6Ib83akwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYTYE y/UPE2/SwzmxqvFUIZm9eAb1fra6X6J741U5Z/RyIvotb2MMtMUgJPE4S3TeDhwB +DYXqwIs1l4EV4gT4yq81W7GK/TB9q1a8mqwFhrozLSnOp7Q3v/R+3Ofrh9MqMzb uQG94LmlBSFipy9C7ND8As6zlBrzWrec4yn0BThVbmFtf8TutqbjyQABQO3g+f+W l3dLmwxs1g1Kcj0hUuxdcaWFFcAe3TRW6llvvhjv6g9IjVqEoBQc5xUj1OBHTz7b sGR7nZR1clEHDLBjaLh58ybyJ/5UZbi5MCv/qer6n9WZW8lgRfC3WzPSIJ34c9Nn UFPy2pLs/Z1I82649g== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/spring.io.crt0000664000000000000000000000240113013560574017030 0ustar -----BEGIN CERTIFICATE----- MIIDhTCCAm2gAwIBAgIJANd9J6BAtBP4MA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCXNwcmluZy5pbzAeFw0xNjAxMzEyMTMz MTBaFw0yNTEyMDkyMTMzMTBaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV BAMMCXNwcmluZy5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0G m+lnjqwqdTaTEzAF4MHZ8TCef84rR3jAvtlI0zoGKoPpE3M7Y8GRrKGsur4HdH2Q U08W2pm1Ve+MHg90K+M83p375Byou/vl1dLvxyBNq5mW2s6jwc6S+sgt0A9jGm7D nJFwdesDey0hRULgvZn3WmzhtI8CmjZ8DwG8ompWw35KupHqpeOrCoYkhZzgFENu pefEaZ97TGOwe/vWjRLyb576N0RpbLnNH2ePQnbMhPJ1eRBhRPL9NNm9GIkHUN5L MkJpkuCi/LYnwopJowNiED79X06vBISy1SNQpNZSEN1/926CI2oeH3dspQ0s1RKT tISlzWp0DZdjnXSKwyMCAwEAAaNQME4wHQYDVR0OBBYEFKiq4jCdiGRESUkCrCzQ PcjDLikeMB8GA1UdIwQYMBaAFKiq4jCdiGRESUkCrCzQPcjDLikeMAwGA1UdEwQF MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJG0neIXxTai+LWapryH8EpUai/rzuY3 qAhgyKOaylwmDQtKRkOmK3jEHRe8f3IIRG9chO7v+sQhTQIE+wTcqo4b+U7WL3dN 0MzhB1+xrLdf+mL6igAV+91MQzN4HG7/vzYoN86BRzQvPSaQF3TPJRAbrMdLwldM r19VLvjVKxVtSMrlj8tat04yPBQnnR+WFWpY6UDdNPCIXWvkUL9BW4GaNQkyXlbo 7nTGSmOQxEthAUiFZ2CZr4WLsbW+1+zkeg7lfutbnmM9hL5cC1TH2QZ2pGblpOcx KlGv2hyLzTjwPa05IAVJ51LK9u/6OGLG8Mt2NXnqBVLIfhyTWbBESak= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/netbeans.org.pem0000664000000000000000000000566113013560574017511 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5xdfTGgcjmuOF pB8oA0d07ciIrrDCNCRRgv7tOPTHM1FPU1gLpdwhHj0YrYeFJpcyD/SXgRH4bAJK izR+rfu9H2vKsAzDj3X2Smjtat2ZUd4z4TykYRB5fXzaO+Zoiwt12FVDYiWVdlWc SkU9iA/Cp3TYUg+bqIBgGh4k1PIxgMOQZGDFi0KpGaW7pL75aGTiyIFoawc8NmwV cOTzbqAvtFrTKn/7iJnkrA+8X+fNHjsDx2adUfHU3Zan8bjhVZKbunF/RtXfSWXo rGh9cOe44erltKEUrR7l89f9nOL41Nj2iTPs0TfbBa769jmtNskNomsFeg0s1Vd1 8Abk3Qx7AgMBAAECggEBAKSm66FZAlbWYy4BxvOJ5H2IeyJZ4qRd3oq4VgYfYyRj IX/zWKgKO07HJFOJCgJDr+JZLepSJYFPCcDUHJTi06pN/RXKb6Wss1q1nMZA32OS oiTNTxhKR3XGeTBbwt2Jz4CFWxy8Ep+kIEDDuxbMT1uxW+iW4uqNsCp9O5ZdfsPL 36M4C6o+tJoLyelAqBMgRwYBAR7U9g3vfYq6bUNzPD4/gZ7YaO6JvtieDTbPwpjc p3iCBgSPRA6ED2yR48LwC/u0piXlsNcBHUFVk872KpGOPHGXnqWIvj7kq9sMCpyU Wo90B+XJ8wuwGMPMjmKwHte2WYYlQCbjLYFVA2VBnzECgYEA4zO33WDgLz001EmP PGW6SoFVo5UD1N9p6AwgYToLqvMiTgi3c6dlRkrEYWaM1bcJnaBYU5OdzkCQGpxC JJA+YaJVTjMZiqo02X+XfANQaPBFVhHBCXwTWIKiJuspLy+0gwYyEwMV1GczQbkE mPUufsDaVt3TwejSMqS2nTQ90EcCgYEA0VHTGWyAs2SO9MUGr+Apfy6miEFUHkLu J33nfVfOwsaZHqpEeSYEeDuTsC64EMmruHhlo/jxDarZhWLhz9QnjAd8mA1fzDaq xexYBgusHofEvYQ5VOH79fhnX0HJT3TCIUOeBs4iaKwWvL9TFI3DuWPYCU+TcD3x KRTNiZ+tEC0CgYEAw6oulkBv0T7s2EXhTSpunOt1TUNv4UvmcSjAWfsbQUXSLVHk a32mAjsxlJA0iXjwlwcYCiH+rTl84O3hKIvwrTSYMphfTsP2b7kqRGq2PSlvDQiN LhXksz0NWGb9ON3kn1IenbDyg9G8msUz6GZ+fDqpzlWLoFtZarPfcNMkyNECgYBU sj0url6tN+U4WXjJNXTVB3VO8NAupnpi9Gj0qND6sw1GATNPqfhpBgJOabkE4fVf 4SePX616EEWP2WDxjTCrUmQxykeXBA+5olZDq/lrKRiMbrIcDIy9DFQXkTD5u47J kuigbEwz+l4A5ZGiYXJu012Y9t/7rLSmIMrCAyAtyQKBgCNxkCNw3mcErowwoiHd fhh4IEsRyd6erVid4jTNb7G7N1lEujlUNY2OsAfhROBy5P/ohJgMKre1nyc1xeiu cZxnQwZetmja4xAnNlcqxsloZlyOrP3APeFQYG3norKirZ4YFeFaU9w/L0kUUFSK N189dwTgx9yqDEP0SEgYJBF8 -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDizCCAnOgAwIBAgIJAKV0wmMGmeB5MA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxFTATBgNVBAMMDG5ldGJlYW5zLm9yZzAeFw0xNTExMDIx NjAzMjFaFw0yNTA5MTAxNjAzMjFaMFwxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApT b21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFTAT BgNVBAMMDG5ldGJlYW5zLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBALnF19MaByOa44WkHygDR3TtyIiusMI0JFGC/u049MczUU9TWAul3CEePRit h4UmlzIP9JeBEfhsAkqLNH6t+70fa8qwDMOPdfZKaO1q3ZlR3jPhPKRhEHl9fNo7 5miLC3XYVUNiJZV2VZxKRT2ID8KndNhSD5uogGAaHiTU8jGAw5BkYMWLQqkZpbuk vvloZOLIgWhrBzw2bBVw5PNuoC+0WtMqf/uImeSsD7xf580eOwPHZp1R8dTdlqfx uOFVkpu6cX9G1d9JZeisaH1w57jh6uW0oRStHuXz1/2c4vjU2PaJM+zRN9sFrvr2 Oa02yQ2iawV6DSzVV3XwBuTdDHsCAwEAAaNQME4wHQYDVR0OBBYEFKBhmoDTcTWo KOIpL/UXSM6XE/pMMB8GA1UdIwQYMBaAFKBhmoDTcTWoKOIpL/UXSM6XE/pMMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAAzj+bVvCKYm19ig8uqDW5g p4Eq/R06LpV0J35iwKRN/YN5lyuIIdAFUtKLDgYxXaqUeh68zDcMyBpOU1o66Ei5 h8OT6quVA8IFmPHGWCt2KCMt58a2GFC92RHtHUFD91xuu2zFakXhZYxJvVPt1xpV QBOixTsW9O/pCO8KQ4Id9RXAgcMHMb9Ngho63cb7+FvSCcHd9/BJ/drO6PbcxqcG fLvHvdlTDV5aL38N0b2N1Ufpnu+btviQnuIiBCB1WWU/7nxE7phl6xVwVmLUCGze U2frDvRtahVe89R+GBz9QiNK+5i7wiz559vBPDFYneG0LVa+FA1scBpFEXwZ/4o= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/spring.io.pem0000664000000000000000000000565113013560574017033 0ustar -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtBpvpZ46sKnU2 kxMwBeDB2fEwnn/OK0d4wL7ZSNM6BiqD6RNzO2PBkayhrLq+B3R9kFNPFtqZtVXv jB4PdCvjPN6d++QcqLv75dXS78cgTauZltrOo8HOkvrILdAPYxpuw5yRcHXrA3st IUVC4L2Z91ps4bSPApo2fA8BvKJqVsN+SrqR6qXjqwqGJIWc4BRDbqXnxGmfe0xj sHv71o0S8m+e+jdEaWy5zR9nj0J2zITydXkQYUTy/TTZvRiJB1DeSzJCaZLgovy2 J8KKSaMDYhA+/V9OrwSEstUjUKTWUhDdf/dugiNqHh93bKUNLNUSk7SEpc1qdA2X Y510isMjAgMBAAECggEBAJlq6MfWON1TcEcJtdO5AocgNgoEIBKwsVjSnuaO+ivS 19PK0KI2IMe74TQhshtZBONpG1VfUElGToJu3SCaw2djy4iNlsAKpVQ/gI7eaNOt yuAOsMjUzr3Z+V+Rr5BVMVTRQXx8GTJfDdMAUydvmu5wMs+kebLsfcydx7ikh+Z8 vrBurG0wM5Uiup3htqQmNB/sETBLpzrdOGQTjTXwTWnJRDG5yjaJP75AKcbTitAS oj0htsW03nKhmm7jBwzV44KGhesaggF9k5OPy8C8OZ5CGu1P80o6r9MRWdd50TTR x/y56DhHG7AL+E7DX5OzrMr6XHPd/qCDQOVCF2eN6cECgYEA2oUrg7ahHO20eQoy kyoesOAUJPAKjBuRLdU5JbOqN4WzWlp/Ttx6L07/AWnMCFS1k2XkfurqqOZojOuh 8Gj8XRQ29VIHy3oGyo+Dysv+7RkUE7JWaUKeeBgRgxGXQMbBjTl3+nciHYBr+aA8 /FMD/JvZVWR6HI9X/MWT48uySfMCgYEAyrPcyQnXVXbSIuwvdlkBnknK1mn5E5ye RRJrCAjniGzjz7FEn9IQW9fm3eWG4gsxTefdZO/MQCdmmMp1q9AoxEwDTTSciuWD 2MS121ozTG3ntGQTAZju2wJ2deG93SDUWHlaDqqipGycAShct2bAEsDv2yoHL2m/ 2orV4ZDJPhECgYB1yMQcucr76dCWUX3TPyfN1OpmwpAc1xsY5k5oWQBN7x4ufIsU edjOOTlQjLMyZl589bYFByC3K4J9OuFN0Xj9vtCkyLN05PBWLKcwH2boa9UbjMvw 7ry2JNsDl+68NqXLNofKFH7qAfexVMKqiyCh/2tVENSVIlqd3+2IIpqWKwKBgE2i DVFB36Lv2xNc+eCNvjztbi4ocCi+ty8lGrD9GA/8BFQrRGkhfvpt+hHKMpqoRr3b q8NYxBVeAcFK6T5gfvyPUERlff8EYDbJQA0+wp7nCPLh0RWviOuASfZj+t+SD0HD WGZ9m8T1g9o9pyTmyXFlS3fY5N+X1M7SlY/KcAjBAoGAQNixliS1YPOw2CYN2cv1 XP4lGPdVeFYU+4DZvFU+kWbFxr/4W+pCPZviiwLDh75wWn8Zq/PNx1BYM/532VSE kciBOUqSgDTX2UCH5VBzf0pOAc+CEco6hI1Nteq0/y1NdrSs1jhNc34Zmb1l28m9 IWsQTbxlnNDpg82xNXnXHVc= -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDhTCCAm2gAwIBAgIJANd9J6BAtBP4MA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCXNwcmluZy5pbzAeFw0xNjAxMzEyMTMz MTBaFw0yNTEyMDkyMTMzMTBaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV BAMMCXNwcmluZy5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0G m+lnjqwqdTaTEzAF4MHZ8TCef84rR3jAvtlI0zoGKoPpE3M7Y8GRrKGsur4HdH2Q U08W2pm1Ve+MHg90K+M83p375Byou/vl1dLvxyBNq5mW2s6jwc6S+sgt0A9jGm7D nJFwdesDey0hRULgvZn3WmzhtI8CmjZ8DwG8ompWw35KupHqpeOrCoYkhZzgFENu pefEaZ97TGOwe/vWjRLyb576N0RpbLnNH2ePQnbMhPJ1eRBhRPL9NNm9GIkHUN5L MkJpkuCi/LYnwopJowNiED79X06vBISy1SNQpNZSEN1/926CI2oeH3dspQ0s1RKT tISlzWp0DZdjnXSKwyMCAwEAAaNQME4wHQYDVR0OBBYEFKiq4jCdiGRESUkCrCzQ PcjDLikeMB8GA1UdIwQYMBaAFKiq4jCdiGRESUkCrCzQPcjDLikeMAwGA1UdEwQF MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJG0neIXxTai+LWapryH8EpUai/rzuY3 qAhgyKOaylwmDQtKRkOmK3jEHRe8f3IIRG9chO7v+sQhTQIE+wTcqo4b+U7WL3dN 0MzhB1+xrLdf+mL6igAV+91MQzN4HG7/vzYoN86BRzQvPSaQF3TPJRAbrMdLwldM r19VLvjVKxVtSMrlj8tat04yPBQnnR+WFWpY6UDdNPCIXWvkUL9BW4GaNQkyXlbo 7nTGSmOQxEthAUiFZ2CZr4WLsbW+1+zkeg7lfutbnmM9hL5cC1TH2QZ2pGblpOcx KlGv2hyLzTjwPa05IAVJ51LK9u/6OGLG8Mt2NXnqBVLIfhyTWbBESak= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/sublimetext.com.pem0000664000000000000000000000567213013560574020250 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9A65QemRSTBP1 bfERCgnvWxceFq9JFSDt8j9yWZAeeppH2CCx9C2ShaVfwN2VztthJkI+t0Q5zgsH 4wdH01VfmDpSReqtTvruTT0/z+d5cQeZ256K4IXPzmFTLx2lA6nHCzU0zBJxHO20 K3GxmE8QF1iPsC7yg3KoFU1G8c+oIV9zwdk4mDl1SfZpzfvRnAOl1eh8FrE2+U55 AXnwJJemkKx4bCdhkeNDfPvDVoBuGdgtqPbcrjwUSqegDPO/OyDzChePTIHSecVR kUlIuDG490UfsT+SSVDHyPVVppHFr8gm0bDSoQ5IbYZbomVzdHY/jOe+ezeRAbpb C1Yhvc5xAgMBAAECggEAIDrLc2+bQak1UglALN6gWQ8YPwoxM24F4m0HQpFhEMFp I00ILi/rwWtGirBRWGUgZU1nyFfpq02l9d9Rc37mtNk5QKQpYwnvocjL4+CooL2U RTj8rMOiLZAMamnDTUr1nTodBXaywlTjd3Bc/6JwANdqQ34QU0v0thKDzdAXz5wu C3UPkITz/CriECDZekjbHTsqY4r8UAwmC+OMknvwhx2ipr77BoYeg8l2PmzqR59F bnUkvpRhWvHKVyKXcLioiecf10VINX2dxA+M2nOwLYc4yMaJ2bJMtZNDWmQVnlbt SdFIThwL6WY1wFIEdmV64ZPC+HyIq1gZU0MI4q6YLQKBgQDpWgAiprXOvIt3DjVI 7ts5/aOkOyfQsAeZkTLqQG7uJ1xRdiJFQnWyqIPucjygrt1khbQFE8q/qz1g2AzM 4wMWvdM2p/tfA4skN3/+3JoLMMECBgFUcPesNBpzQCF8tx0ryatx3rXw+vOEMHes edHhula4tGSccdBQR7RvjqEP2wKBgQDPXA0DHbRnzz46kGEQR5xPAQ0YXjlmp4JY 7YsQHAIbU6zQBAPhfc9DUtXRgYCrkpNF3l+rZNhmXXrXGug+ys5tQBqARHWMlL/G p+iJ8mqmVRgtJ35Uo+piz2GbUGJUhqsV2jFOy93ffGPUbnoJNp5EXOyW/dIhKTWR fg+VdoMCowKBgElaIjrCPtpKyGhXTgasFrum8F66vaxK+UibrO6X7IbuVoXA5crx tj+/2yEEReyYqz1jDhCehRg1AulDYNqy7ZCjgRZoPYtDeOSckZ6Sx9WGsNUrABYE IMa/5iSeXyhuAzx1e3Ai+vxSVmQSPDw6WvBi+8m54vqOiFYEBEMhCZ4LAoGBAIAI FRy0bZyfMIwWc2gK3y9EteIy43xHt0rTOMb0lDRtQMmbgQ3skVm/PrhCHsFRGk/M kwOPm7HwzBUezwFeVYDNUM+b9Xycp6CwMftiy4jyB6BxvyXho6no5Bpy0pPgJqiy dTly1QbVlgonQICJ0cTiH07HX8QL3sB7toGRkCjDAoGBALm9HcVMtJvAecNrlTqO EpyggYwdocnxsBCXwAzHbiV96sAo2RtDzvX1ykWBE1WCAIsYZCNlzO7Rhgtivs9F h7edvxBn3qWWwXwfZao/JQfyJx+ZTsBU2gOZF3RhbVmHx+Q2TkB5HFRF/TI7fZIR Hh60phxnQAzb5kDBAEUbfjvm -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDkTCCAnmgAwIBAgIJAKNVhjJ4JVJsMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxGDAWBgNVBAMMD3N1YmxpbWV0ZXh0LmNvbTAeFw0xNjA0 MTQxOTUwMTFaFw0yNjAyMjExOTUwMTFaMF8xCzAJBgNVBAYTAkFVMRMwEQYDVQQI DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQx GDAWBgNVBAMMD3N1YmxpbWV0ZXh0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAL0DrlB6ZFJME/Vt8REKCe9bFx4Wr0kVIO3yP3JZkB56mkfYILH0 LZKFpV/A3ZXO22EmQj63RDnOCwfjB0fTVV+YOlJF6q1O+u5NPT/P53lxB5nbnorg hc/OYVMvHaUDqccLNTTMEnEc7bQrcbGYTxAXWI+wLvKDcqgVTUbxz6ghX3PB2TiY OXVJ9mnN+9GcA6XV6HwWsTb5TnkBefAkl6aQrHhsJ2GR40N8+8NWgG4Z2C2o9tyu PBRKp6AM8787IPMKF49MgdJ5xVGRSUi4Mbj3RR+xP5JJUMfI9VWmkcWvyCbRsNKh DkhthluiZXN0dj+M5757N5EBulsLViG9znECAwEAAaNQME4wHQYDVR0OBBYEFGRx UCvrqmTwehwfmKdtkJTR7MOTMB8GA1UdIwQYMBaAFGRxUCvrqmTwehwfmKdtkJTR 7MOTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADMNb/vweUJ6KXte 6fbgMqzDvdxy+0oDs/NdzWXGLeC5Y1XnO3qhZ8LBeLkDbsKFB5juzbxaQerUFR9e kQZCVlkr85VHwGYXw5FStUkxSsMS5JdXeSdps2JvXBjBNVX75LVNfLp0tZmJNQgu OyTTG/u7lJ4KN4PsRkj37IvaCwV2i5FvB2wbeX7N4KbM/uvmJjkILUh4m4D7iGtj PIDxCdb8P6EnFREBDDRzuZjVaOkNknA6x7V96N6YGtg7ypCLlmNqabcuRY8/eO5C G5nTAKU8l9JuLE+yzgYt2vrXf/8/uKmD9QaKdkzsSup7fNImUW1QismyHOwqpC9z TBbfEG0= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/developer.android.com.crt0000664000000000000000000000246613013560574021314 0ustar -----BEGIN CERTIFICATE----- MIIDqzCCApOgAwIBAgIJANM5Fcvms7E/MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSgwJgYDVQQKDB9BbmRyb2lkIGRl dmVsb3BlciBrZXkgZm9yIHRlc3RzMR4wHAYDVQQDDBVkZXZlbG9wZXIuYW5kcm9p ZC5jb20wHhcNMTQwODI4MDgyMzQyWhcNMjQwNzA2MDgyMzQyWjBsMQswCQYDVQQG EwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEoMCYGA1UECgwfQW5kcm9pZCBkZXZl bG9wZXIga2V5IGZvciB0ZXN0czEeMBwGA1UEAwwVZGV2ZWxvcGVyLmFuZHJvaWQu Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA059PR5G1Ny1TFCaM 2EIoAh7L9xbY4Yj68cdyT3IXPgO7Liy/oVyXRyJyAIdpqwMURynLpXkedus7069x qpodHJAt0W2lAwq0/dpeBghKAYqQcAOZnQ/diDPVFYCDy3puFpRP1wDIauh8aVrd 1pZaI6NM7fTwIGkHMaenR72agMwYS75Mcwup6NlPK6eOdCpMZzhOQ+3aRzSh6fAo AVpb8JK8i+MzLs/mUnXJFsWLPspEB0MJ7gx5xciiP1TL3VMnb5sVgs7lO7OvFREi QuwcrLYKTBpDLGhhGBZDDupxM7XNJPIKiIuWdi8Dl6094UXT0lRx7qqf7GgjDyE4 iLQUWQIDAQABo1AwTjAdBgNVHQ4EFgQUs7PCZ/tV4Cfh1/UD9uiuJLnOIS8wHwYD VR0jBBgwFoAUs7PCZ/tV4Cfh1/UD9uiuJLnOIS8wDAYDVR0TBAUwAwEB/zANBgkq hkiG9w0BAQsFAAOCAQEAGgmIDe7aBeSsqr92Sh/hh1aEKxXbPSVpcKc7u8PS0/Y6 SA/2NbduLod/rY3YYMQFmbuzACFFPngdyrT4vnQp7NuMv0BEGJeAWs8jLf31x7zT pCaE7aRr+v3m5PVE1T9r7xrpeUkuKUZdKpLb/zwQGHzTQh8hOwpHWkOeaPhbeyM3 9D3v1huHumwTevKlz8DstGT+cUtSzG8xFG/eCCJYts3NgCYAunwuMbt3hO4BoANf 4sdR/MUPXxL4gSL/W8cVqwoukx2TmjvBYLyChSGNK4PZ6nfCNLrtSkXE0oKxyaLp FB8jsk738QvcVJALvN5gHW6gVY6O5o66tcCc/CPN/A== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/github.com.pem0000664000000000000000000000565513013560574017166 0ustar -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCv2ir1GPdJjOYE KNnPsnAmdPBBu31JcTCfegv5GmpdBrdNcNsc8OivN/y+9yjWezwDr4macw6Ji8sG hO8jh+eCOgjZ8/4alA6hB+xNoG4NDLM6wm/YTlxs5lDNKRzKSuiXHUPCSp3L/YHP bli09f48GLrGlUItIGRp3mJlbn7J3qaWgbvrrXQqgFEHRL4YIPpoJU4el6V5nmcl gc7qjACgYKd0egxHgwzrR4e8HaoaCeip3ha4RBmyuHaapJ9fR0f0klQe8E8t/PcT HS6Hr2qgpGtrbL82ujq90PPLnQXZUIyzoWu7y6frLRFYFRePaI/64xj5uPcPUmn4 h0xMfqMBAgMBAAECggEACGHp8k0CXKsuu7wGxfPHjM2+NiPt0PZoTvHOaE1uDIkp a7OZfkOtk8yja6b0d2Tgc3yGnqolY0EaqHDlxVfRHVAO4/TRhArSt7Jc/UZMeKrG UGK8Wh9CIJ7J8z2mda4kcC+g7z4HT5YB/hVQfS/MsqirHpQ211fX8YP8RMGDobO7 Bmc9A7XGQWo+aFYuqcctpK05WrWOK8GCgfCyLLaOklEkCgxJmgoRS9tdQ9HI4RHY EnnyJQJbUeE9QpMshR5fRE2RvnFSsDVrsVwMdSvqDHi1rPGQDozF5mv3V0Cy/P/T QM+jC0hQs9GuuOXatfpxtizyBcJmjBLJPs3VDXwlEQKBgQDn2Ii72pJqK6QlAug1 ordK3t+97/xiKPkT/G6fWOKR/22da7CW+1TyD+CXcjWPA4LCEnM7OeepEYKew3HU EvrCBg3wO7kXOUFyjNNL7LfKx73jItBq9JPuhwlbUZnirzzIJrwumcSp6cl3IE4y t77tf3MX8ktH0bUt282wPPM5QwKBgQDCLEAtYyatoGrF3U6FLx2v4DpAiSoa49jt 64RDHuCPAf9NS/TBJyrhqi4j0VwVnAp/uQON5Oqr8H0K/YOA3e0bLrHI2CXA2DTO YElokcJCZZ86IqZokmOOfhV2x13ACL2KJwuZ/A6IUdQm9DS74g6eK5Fr/jc/Q2ey o9kWtU48awKBgQDfNBH/eJ/44ub2UuQnru1zgTo6a+64ueWCHkaJ1lLaZ+Sp52Ft Ga5gFHUOmH+Dncem+4hAfrDOjfMI0fSmTVdor9d/bp/1AcRGedl6gP04li/zmjK4 pZo9y3dwmRDjsf18W/5ThupVAqRYsZtXLJr9nvO5HCTpkbUx3ykZALTQbQKBgQCN o7XU5eTK9p+sYfjrEil3p/sWJHhAUUBmnUxHofhwmSZgfi210BpprrgljIy9fqvx 60X6dafxcGXmZHNOx5Q0JeWt+m3ftFcgzAAAdYLc6EA0Kh51XYOd579Ee72ZXUbV xhGia8k2C2rUV4M4InhDTMixnCk0zriQCRFMjUjarQKBgCVNex03rtGulS4TNt1R ggsUa1xRoNnAfbXAE4W97akEuljL6jZiiF6IT3kM8Sckkt02bloy/+DlBjixroqp zr3gRzDmE85lDYnOYm8z42fJ8JkVgbyGUdFlolqzROAP9PaBTMs2lT4trS/UMSm4 N6DD3fKNNZRv6ZhkrvlbS+2D -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDhzCCAm+gAwIBAgIJAPN26r3EAAhsMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmdpdGh1Yi5jb20wHhcNMTYwMTMxMTQx OTQxWhcNMjUxMjA5MTQxOTQxWjBaMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD VQQDDApnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA r9oq9Rj3SYzmBCjZz7JwJnTwQbt9SXEwn3oL+RpqXQa3TXDbHPDorzf8vvco1ns8 A6+JmnMOiYvLBoTvI4fngjoI2fP+GpQOoQfsTaBuDQyzOsJv2E5cbOZQzSkcykro lx1Dwkqdy/2Bz25YtPX+PBi6xpVCLSBkad5iZW5+yd6mloG76610KoBRB0S+GCD6 aCVOHpeleZ5nJYHO6owAoGCndHoMR4MM60eHvB2qGgnoqd4WuEQZsrh2mqSfX0dH 9JJUHvBPLfz3Ex0uh69qoKRra2y/Nro6vdDzy50F2VCMs6Fru8un6y0RWBUXj2iP +uMY+bj3D1Jp+IdMTH6jAQIDAQABo1AwTjAdBgNVHQ4EFgQU6p1ApP9amffHE/US lXsqax3qhFIwHwYDVR0jBBgwFoAU6p1ApP9amffHE/USlXsqax3qhFIwDAYDVR0T BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoPMNVOSchGgKjTjnQcBspTKN3jI6 We3k2DCBV8i2J03v9wy8QtslOfAwY7Mm8wJJDLjtZwmxNAGEWiabvbEs2aehL98O zWnXOxL4ZxIH4Mgld4L+ihml6n2yFpF8z66wx+x8NqG5tfpeVztgJMns4jmfE8Kg g1aZhPYjkvMRqcom/Lg+lSNh/7g4DUyx9gNikQUySDDKnrRu1qtrI+c+TsGBq45K uQnbCefDQdEc340P/GAqkBHbOdVOwGjnhlk8LyAjqse0YicLs7qnFojp55Cwn8Nd KI6aj9+JN/EYOnv0Q9ywUDCrRPs87QHudv81v2vscBnTzJu+ox8iUPorDQ== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/sublimetext.com.crt0000664000000000000000000000242213013560574020245 0ustar -----BEGIN CERTIFICATE----- MIIDkTCCAnmgAwIBAgIJAKNVhjJ4JVJsMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxGDAWBgNVBAMMD3N1YmxpbWV0ZXh0LmNvbTAeFw0xNjA0 MTQxOTUwMTFaFw0yNjAyMjExOTUwMTFaMF8xCzAJBgNVBAYTAkFVMRMwEQYDVQQI DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQx GDAWBgNVBAMMD3N1YmxpbWV0ZXh0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAL0DrlB6ZFJME/Vt8REKCe9bFx4Wr0kVIO3yP3JZkB56mkfYILH0 LZKFpV/A3ZXO22EmQj63RDnOCwfjB0fTVV+YOlJF6q1O+u5NPT/P53lxB5nbnorg hc/OYVMvHaUDqccLNTTMEnEc7bQrcbGYTxAXWI+wLvKDcqgVTUbxz6ghX3PB2TiY OXVJ9mnN+9GcA6XV6HwWsTb5TnkBefAkl6aQrHhsJ2GR40N8+8NWgG4Z2C2o9tyu PBRKp6AM8787IPMKF49MgdJ5xVGRSUi4Mbj3RR+xP5JJUMfI9VWmkcWvyCbRsNKh DkhthluiZXN0dj+M5757N5EBulsLViG9znECAwEAAaNQME4wHQYDVR0OBBYEFGRx UCvrqmTwehwfmKdtkJTR7MOTMB8GA1UdIwQYMBaAFGRxUCvrqmTwehwfmKdtkJTR 7MOTMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADMNb/vweUJ6KXte 6fbgMqzDvdxy+0oDs/NdzWXGLeC5Y1XnO3qhZ8LBeLkDbsKFB5juzbxaQerUFR9e kQZCVlkr85VHwGYXw5FStUkxSsMS5JdXeSdps2JvXBjBNVX75LVNfLp0tZmJNQgu OyTTG/u7lJ4KN4PsRkj37IvaCwV2i5FvB2wbeX7N4KbM/uvmJjkILUh4m4D7iGtj PIDxCdb8P6EnFREBDDRzuZjVaOkNknA6x7V96N6YGtg7ypCLlmNqabcuRY8/eO5C G5nTAKU8l9JuLE+yzgYt2vrXf/8/uKmD9QaKdkzsSup7fNImUW1QismyHOwqpC9z TBbfEG0= -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/nodejs.org.crt0000664000000000000000000000240513013560574017174 0ustar -----BEGIN CERTIFICATE----- MIIDhzCCAm+gAwIBAgIJAM0RuxL089KdMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCm5vZGVqcy5vcmcwHhcNMTYwMTE3MjM1 MzQ2WhcNMjUxMTI1MjM1MzQ2WjBaMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD VQQDDApub2RlanMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 2BMk7kFXmVV6KDiAIK/KXB1K03JUKqziyr1VbqZE++i/qJ7u/psK5+tbeksktBvP HeJZOqXdcICNo+kZwM9/gvH4WQ8u4LMg+ZWCvPzLcnkDd1r1hg2eND5m+E3VkVES /KL3AcaBNadfk/oAXIT1nVjvl2ZUlsRaYzb09Whr5995XTVw+ZntDoHrgjAHoYNq Erqc0/Cbv2Da0LHtUYRgUFFUQmBKOtbB+r2f7KYP8lCKxkISDxrq/je3tYJcUPfm aBFKcTmHgQa+WHK+AznZCtvpMicm/odh0K/mg8o0tADx7A56lTsedNI5DB8D90Es 2X4LzHuhhXPLxP8jUQbgLQIDAQABo1AwTjAdBgNVHQ4EFgQU44gu/w7Juo2HIvWV pGfZbgnY15MwHwYDVR0jBBgwFoAU44gu/w7Juo2HIvWVpGfZbgnY15MwDAYDVR0T BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVZItQ973u+yzHF1zQXGmhDIRQrcZ 5r4zmnT0VJhcZiPh3kDJfX9YnSLY2zYWB34UHhrO8Zp+55dv8e99y0RYgtQQgt+b K8D4U2NP1qBDAiFkOhKdVgXLL7r+MjZpGFTr75GDvFZQDyP+T1GUw++XSVVYQhFP x4RwSwMmUNv80uHMRrcPYe6a8XKCa1li/OlBJQq/JpFyhITDuo4aMVRcPK0HAfJE M+ZMM9mmHrrCqazFo0qThbJCz0hRqKZGMphjJ4kdPt3Y8536fZsEzTcR6PhLCOvd 4AovC7EmDmY9o2FXpPDmt8GpxenMdRRZkV+DkBv8OGcpsSLJ2vhflVm2MA== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/community.unity.com.crt0000664000000000000000000000243613013560574021100 0ustar -----BEGIN CERTIFICATE----- MIIDmTCCAoGgAwIBAgIJAO43IwlPESOWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxHDAaBgNVBAMME2NvbW11bml0eS51bml0eS5jb20wHhcN MTYwNzA4MTQ0MTM1WhcNMjYwNTE3MTQ0MTM1WjBjMQswCQYDVQQGEwJBVTETMBEG A1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg THRkMRwwGgYDVQQDDBNjb21tdW5pdHkudW5pdHkuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA6vvAUvtTkVOwVadicD+YgTiOfmeER3Vg253rXErJ Er/Qg/AxhnVaIz0EB643DNZnPA3zG+XtWs+CsQfxPTqaRx/I01Pc7w+XAsQmSImq 4gs+shtYywzxTqZX1CIj9imO3AINiOifCfVXp75MlqXQqzcLmaldO2G20Wc0PCqr r7i6Y9+cjVv4UBZUc8Goo6b5Aih/8OR7pjsfqpm2zGLvTXKR49nwI4ErzW+1Dnw6 iCY094UkAtQOJ4q1PvOZOCwGADK3SNuwo0zRUFNhFqzMbDec0YW5bRjFGmUYNGHE PfRLlV0Y88YCQv7iMqbY1pdivSofFqeEyfLhodMgxZWZjQIDAQABo1AwTjAdBgNV HQ4EFgQUo4DDPR/7sDyPoGK+tFAB6Ib83akwHwYDVR0jBBgwFoAUo4DDPR/7sDyP oGK+tFAB6Ib83akwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYTYE y/UPE2/SwzmxqvFUIZm9eAb1fra6X6J741U5Z/RyIvotb2MMtMUgJPE4S3TeDhwB +DYXqwIs1l4EV4gT4yq81W7GK/TB9q1a8mqwFhrozLSnOp7Q3v/R+3Ofrh9MqMzb uQG94LmlBSFipy9C7ND8As6zlBrzWrec4yn0BThVbmFtf8TutqbjyQABQO3g+f+W l3dLmwxs1g1Kcj0hUuxdcaWFFcAe3TRW6llvvhjv6g9IjVqEoBQc5xUj1OBHTz7b sGR7nZR1clEHDLBjaLh58ybyJ/5UZbi5MCv/qer6n9WZW8lgRfC3WzPSIJ34c9Nn UFPy2pLs/Z1I82649g== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/www.rust-lang.org.crt0000664000000000000000000000242613013560574020454 0ustar -----BEGIN CERTIFICATE----- MIIDlTCCAn2gAwIBAgIJAO2Bl4dLamtDMA0GCSqGSIb3DQEBCwUAMGExCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQxGjAYBgNVBAMMEXd3dy5ydXN0LWxhbmcub3JnMB4XDTE1 MTEwNjA4NTAxMFoXDTI1MDkxNDA4NTAxMFowYTELMAkGA1UEBhMCRlIxEzARBgNV BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 ZDEaMBgGA1UEAwwRd3d3LnJ1c3QtbGFuZy5vcmcwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQDVplHGBWABxRoizmlVbeSPoF7ma8lTzwGZ4Rd5beOzSEhh 5MdTNJa/eCEsH9lxHUKfR42FltzZg9Aggx9Bo+GaT3Alrt3BYasw8rc23Yt12Qfg bjBB6qVfndW9acaJU6DWRErDTLocgW+d77uXPKJySqWLlXCZ5XuxTvWYeiqqI7af mr90cQ89yEoYosluKRAiYcE+WFPq8YWDpg8LbgOSRmj06+P6ap0Jh+yB1//awOGd LIj7HzJ1mJBKcJWapItwhI7TQmrI4vuFFsQVofawW2rj2Cp38Cj1JJnaksFzW9+V BOoqLfV8VvgEPRrdrbpSVtYGAyppaIXaNketwQeXAgMBAAGjUDBOMB0GA1UdDgQW BBSZ0A9gOD5XYyFFBey1+vZt+QNg/TAfBgNVHSMEGDAWgBSZ0A9gOD5XYyFFBey1 +vZt+QNg/TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDFlTnebTgQ 12xZuGDBs1akL6IIopJBfAtAZ4VKb4Hs096WRW4FRoTITZekvttj5PpC60rwCktO wzyvBAaTyyAEFTdJwYDkjQyOn1f/s09dwSJGGRE7m+32gWhJ5wHyYioaq2g/6HZK LEw/URV/ZbC3b6WGajNjKeze9WzR9j7lPwMY1bTyD7PrATI0X/0/Kpb0vB7thoUj FPSmCdOhAvtbwHk14ZYR+cuZF3eKjuwOPQvBgImKSshUa+xny5iypcrGoRSz8TR0 L8JtHyryhBvAOlE1ZxsQ1KGNLkWhSq+IXu62Sn3ypWvzcK12oJleCVVfs4SeyNPa g08xyaMtt/iS -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/data/developer.android.com.pem0000664000000000000000000000574213013560574021305 0ustar -----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDTn09HkbU3LVMU JozYQigCHsv3FtjhiPrxx3JPchc+A7suLL+hXJdHInIAh2mrAxRHKculeR526zvT r3Gqmh0ckC3RbaUDCrT92l4GCEoBipBwA5mdD92IM9UVgIPLem4WlE/XAMhq6Hxp Wt3Wllojo0zt9PAgaQcxp6dHvZqAzBhLvkxzC6no2U8rp450KkxnOE5D7dpHNKHp 8CgBWlvwkryL4zMuz+ZSdckWxYs+ykQHQwnuDHnFyKI/VMvdUydvmxWCzuU7s68V ESJC7BystgpMGkMsaGEYFkMO6nEztc0k8gqIi5Z2LwOXrT3hRdPSVHHuqp/saCMP ITiItBRZAgMBAAECggEBAKxd4jElGTksDbMoAyhSGkw/0VocneJ1tBAip5TWFOBK Ibfmct93jzA9eiW8JfFIvMeJ33mUQaAS0dQF3staY8PUG72tVO45Vlo99r9rGPxQ ZH0YMZKgTYyWy0SMPM0Ll4eEndM9rACIBG27uV0Dcb/9Trey/bMoWNe0+qeQY7vr BMLZz90zcFgLuRL5errPIvYCpiz22HQxXFo1+KlkXtCtwAyKpJ2Lu5ey9u04Ugng gCzsDPix1u5yYbcSEMfbKCeyMQEEiXahaLbk2I/U8CuHrZxkBTArl8xunRcAqqNk kO/MhNTTQO1c/dKB6KQJ/TqCz6AjhzT6D47HT2G3wJECgYEA+3J8K+I+4o6kuVDi jgHlApSuUyaDjCIdrwE26ujOOisjTDqB/p/vyJcZXOzYlxe1d0dNcxvkLwqk3jH8 f/jCCMy3d+xvmf8pME7be3N7TpBAluA4/5GaByVly0igkNUREVQrEugimgpn3BX6 kOhvX0tbzO/pvyhX62NyKPhUSTsCgYEA13Q6JzUvKXobVbs4V50POLmEL8s6vkZ/ g5JeaVrINncC+S3b0aEd9RXa7FhaQ2NS1BcWoftjSDd1tzsUKIxTCvDM0pNB1fRN a0NzBXUA94tvNfosVvDDJgTYIadCyjtjeIThpes5Zzrto8ckeX5+Ze0o+dj3cC1a m37+DAKYX3sCgYEAw+JBR7KeSMLVIqUXiYeCT8tiLtbPHikptL8eeExa9EfM3MKr qKASHdNQZ+r/JF3M+ZorhOQSlG8XVx3b1hoFlvNcbmlb271C6iZUp8ykH+US3Dbb UIWuV6jTr1Tp+UpzXGuUjssWwagflv3sUF0y/irn3jR8hXW5YF/9fFtQ1icCgYEA zRyKLD9Wib8EfOaCae5MymzaqgFpCDHnPSPAG75gMnG0c/IzfetLsMJAq5YlQFgz R1Q/qK/BQcQCnhBxTXThrd22sJWeLIiql34b50sPQ5sLobBsO8xzjCM6ezdXv10w glDG3QUFngAcsjlowP0qafCQfOMQFUwoITaRtm9WDjcCgYBAzawqKntYEavAYnMW 12O4f2Ms3g0xcyLqj3OcCUlhe9tqT20EDe/FGmTZYDhDqTQYjqHOCxhI5cNq49/n GO6MU4Gd3gfL27NjqIfiMEWwqWcLeeUEBQGmNN5XMLZ5+Ro2koyLrO7SJpmB5VRn 0v6kiANcQGQ6wXdH9XfSXq5jQg== -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDqzCCApOgAwIBAgIJANM5Fcvms7E/MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSgwJgYDVQQKDB9BbmRyb2lkIGRl dmVsb3BlciBrZXkgZm9yIHRlc3RzMR4wHAYDVQQDDBVkZXZlbG9wZXIuYW5kcm9p ZC5jb20wHhcNMTQwODI4MDgyMzQyWhcNMjQwNzA2MDgyMzQyWjBsMQswCQYDVQQG EwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEoMCYGA1UECgwfQW5kcm9pZCBkZXZl bG9wZXIga2V5IGZvciB0ZXN0czEeMBwGA1UEAwwVZGV2ZWxvcGVyLmFuZHJvaWQu Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA059PR5G1Ny1TFCaM 2EIoAh7L9xbY4Yj68cdyT3IXPgO7Liy/oVyXRyJyAIdpqwMURynLpXkedus7069x qpodHJAt0W2lAwq0/dpeBghKAYqQcAOZnQ/diDPVFYCDy3puFpRP1wDIauh8aVrd 1pZaI6NM7fTwIGkHMaenR72agMwYS75Mcwup6NlPK6eOdCpMZzhOQ+3aRzSh6fAo AVpb8JK8i+MzLs/mUnXJFsWLPspEB0MJ7gx5xciiP1TL3VMnb5sVgs7lO7OvFREi QuwcrLYKTBpDLGhhGBZDDupxM7XNJPIKiIuWdi8Dl6094UXT0lRx7qqf7GgjDyE4 iLQUWQIDAQABo1AwTjAdBgNVHQ4EFgQUs7PCZ/tV4Cfh1/UD9uiuJLnOIS8wHwYD VR0jBBgwFoAUs7PCZ/tV4Cfh1/UD9uiuJLnOIS8wDAYDVR0TBAUwAwEB/zANBgkq hkiG9w0BAQsFAAOCAQEAGgmIDe7aBeSsqr92Sh/hh1aEKxXbPSVpcKc7u8PS0/Y6 SA/2NbduLod/rY3YYMQFmbuzACFFPngdyrT4vnQp7NuMv0BEGJeAWs8jLf31x7zT pCaE7aRr+v3m5PVE1T9r7xrpeUkuKUZdKpLb/zwQGHzTQh8hOwpHWkOeaPhbeyM3 9D3v1huHumwTevKlz8DstGT+cUtSzG8xFG/eCCJYts3NgCYAunwuMbt3hO4BoANf 4sdR/MUPXxL4gSL/W8cVqwoukx2TmjvBYLyChSGNK4PZ6nfCNLrtSkXE0oKxyaLp FB8jsk738QvcVJALvN5gHW6gVY6O5o66tcCc/CPN/A== -----END CERTIFICATE----- ubuntu-make-16.11.1ubuntu1/tests/medium/0000775000000000000000000000000013013560574014760 5ustar ubuntu-make-16.11.1ubuntu1/tests/medium/__init__.py0000664000000000000000000002633613013560574017103 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for basic CLI commands""" import os import pwd import subprocess from ..tools import get_root_dir, get_tools_helper_dir, LoggedTestCase, get_docker_path, get_data_dir, INSTALL_DIR, \ BRANCH_TESTS, SYSTEM_UMAKE_DIR from time import sleep class ContainerTests(LoggedTestCase): """Container-based tests utilities""" DOCKER_USER = "user" DOCKER_TESTIMAGE = "didrocks/docker-umake-manual" UMAKE_TOOLS_IN_CONTAINER = "/umake" APT_FAKE_REPO_PATH = "/apt-fake-repo" in_container = True def setUp(self): super().setUp() # this will call other parents of ContainerTests ancestors, like LargeFrameworkTests self.umake_path = get_root_dir() self.install_base_path = os.path.expanduser("/home/{}/{}".format(self.DOCKER_USER, INSTALL_DIR)) self.binary_dir = self.binary_dir.replace(os.environ['HOME'], "/home/{}".format(self.DOCKER_USER)) self.image_name = self.DOCKER_TESTIMAGE if not hasattr(self, "hosts"): self.hosts = {} if not hasattr(self, "additional_local_frameworks"): self.additional_local_frameworks = [] command = [get_docker_path(), "run"] # bind master used for testing tools code inside the container runner_cmd = "mkdir -p {}; ln -s {}/ {};".format(os.path.dirname(get_root_dir()), self.UMAKE_TOOLS_IN_CONTAINER, get_root_dir()) local_framework_dir = "/home/{}/.umake/frameworks/".format(self.DOCKER_USER) runner_cmd += "mkdir -p {};".format(local_framework_dir) for additional_framework in self.additional_local_frameworks: runner_cmd += "cp {} {};".format( os.path.join(self.UMAKE_TOOLS_IN_CONTAINER, additional_framework), local_framework_dir) if not BRANCH_TESTS: # create a system binary which will use system umake version (without having the package installed) bin_umake = "/usr/bin/umake" runner_cmd += "echo '#!/usr/bin/env python3\nfrom umake import main\nif __name__ == \"__main__\":" \ "\n main()'>{bin_umake}; chmod +x {bin_umake};".format(bin_umake=bin_umake) # start the local server at container startup for port, hostnames in self.hosts.items(): ftp_redir = hasattr(self, 'ftp') for hostname in hostnames: if "-h" not in command: command.extend(["-h", hostname]) runner_cmd += ' echo "127.0.0.1 {}" >> /etc/hosts;'.format(hostname) runner_cmd += "{} {} 'sudo -E env PATH={} VIRTUAL_ENV={} {} {} {} {}';".format( os.path.join(get_tools_helper_dir(), "run_in_umake_dir_async"), self.UMAKE_TOOLS_IN_CONTAINER, os.getenv("PATH"), os.getenv("VIRTUAL_ENV"), os.path.join(get_tools_helper_dir(), "run_local_server"), str(port), str(ftp_redir), " ".join(hostnames) if port == 443 else "") if ftp_redir: runner_cmd += "/usr/bin/twistd ftp -p 21 -r {};".format(os.path.join(get_data_dir(), 'server-content', hostnames[0])) if hasattr(self, "apt_repo_override_path"): runner_cmd += "sh -c 'echo deb file:{} / > /etc/apt/sources.list'; apt-get update;".format( self.apt_repo_override_path) runner_cmd += "/usr/sbin/sshd -D" # we bindmount system umake directory if not BRANCH_TESTS: command.extend(["-v", "{system_umake}:{system_umake}".format(system_umake=SYSTEM_UMAKE_DIR)]) command.extend(["-d", "-v", "{}:{}".format(self.umake_path, self.UMAKE_TOOLS_IN_CONTAINER), "--dns=8.8.8.8", "--dns=8.8.4.4", # suppress local DNS warning self.image_name, 'sh', '-c', runner_cmd]) self.container_id = subprocess.check_output(command).decode("utf-8").strip() self.container_ip = subprocess.check_output([get_docker_path(), "inspect", "-f", "{{ .NetworkSettings.IPAddress }}", self.container_id]).decode("utf-8").strip() # override with container paths self.conf_path = os.path.expanduser("/home/{}/.config/umake".format(self.DOCKER_USER)) sleep(5) # let the container and service starts def tearDown(self): subprocess.check_call([get_docker_path(), "stop", "-t", "0", self.container_id], stdout=subprocess.DEVNULL) subprocess.check_call([get_docker_path(), "rm", self.container_id], stdout=subprocess.DEVNULL) super().tearDown() # this will call other parents of ContainerTests ancestors, like LargeFrameworkTests def command(self, commands_to_run): """Return a string for a command line ready to run in docker""" return " ".join(self.command_as_list(commands_to_run)) def command_as_list(self, commands_to_run): """Return a list for a command line ready to run in docker""" if isinstance(commands_to_run, list): commands_to_run = " ".join(commands_to_run) return ["ssh", "-i", os.path.join(get_root_dir(), "docker", "umake_docker"), "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-t", "-q", "{}@{}".format(self.DOCKER_USER, self.container_ip), "{} {} '{}'".format(os.path.join(get_tools_helper_dir(), "run_in_umake_dir"), self.UMAKE_TOOLS_IN_CONTAINER, commands_to_run)] def check_and_kill_process(self, process_grep, wait_before=0, send_sigkill=False): """Check a process matching process_grep exists and kill it""" sleep(wait_before) if not self._exec_command(self.command_as_list("{} {} {}".format(os.path.join(get_tools_helper_dir(), "check_and_kill_process"), send_sigkill, " ".join(process_grep))))[0]: raise BaseException("The process we try to find and kill can't be found".format(process_grep)) def _get_path_from_desktop_file(self, key, abspath_transform=None): """get the path referred as key in the desktop filename exists""" command = self.command_as_list([os.path.join(get_tools_helper_dir(), "get_path_from_desktop_file"), self.desktop_filename, key]) success, stdout, stderr = self._exec_command(command) if success: path = stdout if not path.startswith("/") and abspath_transform: path = abspath_transform(path) else: raise BaseException("Unknown failure from {}".format(command)) return path def _exec_command(self, command): """Exec the required command inside the container, returns if it exited with 0 or 1 + stdout/stderr""" proc = subprocess.Popen(command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) (stdout, stderr) = proc.communicate() # convert in strings and remove remaining \n if stdout: stdout = stdout.decode("utf-8").strip() if stderr: stderr = stderr.decode("utf-8").strip() return_code = proc.returncode if return_code == 0: return (True, stdout, stderr) elif return_code == 1: return (False, stdout, stderr) raise BaseException("Unknown return code from {}".format(command)) def get_launcher_path(self, desktop_filename): """Return launcher path inside container""" command = self.command_as_list([os.path.join(get_tools_helper_dir(), "get_launcher_path"), desktop_filename]) return self._exec_command(command)[1] def launcher_exists_and_is_pinned(self, desktop_filename): """Check if launcher exists and is pinned inside the container""" command = self.command_as_list([os.path.join(get_tools_helper_dir(), "check_launcher_exists_and_is_pinned"), desktop_filename]) return self._exec_command(command)[0] def path_exists(self, path): """Check if a path exists inside the container""" # replace current user home dir with container one. path = path.replace(os.environ['HOME'], "/home/{}".format(self.DOCKER_USER)) command = self.command_as_list([os.path.join(get_tools_helper_dir(), "path_exists"), path]) return self._exec_command(command)[0] def remove_path(self, path): """Remove targeted path""" path = path.replace(os.environ['HOME'], "/home/{}".format(self.DOCKER_USER)) command = self.command_as_list([os.path.join(get_tools_helper_dir(), "remove_path"), path]) self._exec_command(command) def is_in_path(self, filename): """Check inside the container if filename is in PATH thanks to which""" return self._exec_command(self.command_as_list(["bash", "-l", "which", filename]))[0] def is_in_group(self, group): """Check inside the container if the user is in a group""" command = self.command_as_list([os.path.join(get_tools_helper_dir(), "check_user_in_group"), group]) return self._exec_command(command)[0] def get_file_perms(self, path): """return unix file perms string for path from the container""" command = self.command_as_list([os.path.join(get_tools_helper_dir(), "get_file_perms"), path]) success, stdout, stderr = self._exec_command(command) if success: return stdout else: raise BaseException("Unknown failure from {}".format(command)) def create_file(self, path, content): """Create file inside the container.replace in path current user with the docker user""" try: src_user = os.getlogin() except FileNotFoundError: # fallback for container issues when trying to get login src_user = pwd.getpwuid(os.getuid())[0] path = path.replace(src_user, self.DOCKER_USER) dir_path = os.path.dirname(path) command = self.command_as_list(["mkdir", "-p", dir_path, path]) if not self._exec_command(command)[0]: raise BaseException("Couldn't create {} in container".format(path)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_go.py0000664000000000000000000000217113013560574016777 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for go""" from . import ContainerTests import os from ..large import test_go class GoInContainer(ContainerTests, test_go.GoTests): """This will test the Go integration inside a container""" def setUp(self): self.hosts = {443: ["golang.org"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "go", "go-lang") ubuntu-make-16.11.1ubuntu1/tests/medium/test_baseinstaller.py0000664000000000000000000000271613013560574021227 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for base installer framework in container""" from . import ContainerTests import os from ..large import test_baseinstaller class BaseInstallerInContainer(ContainerTests, test_baseinstaller.BaseInstallerTests): """This will install the Base Framework inside a container""" TIMEOUT_START = 10 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {8765: ["localhost"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') self.additional_local_frameworks = [os.path.join("tests", "data", "testframeworks", "baseinstallerfake.py")] super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "base", "base-framework") ubuntu-make-16.11.1ubuntu1/tests/medium/test_kotlin.py0000664000000000000000000000350613013560574017675 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2016 Canonical # # Authors: # Omer Sheikh # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for kotlin""" from . import ContainerTests import os from ..large import test_kotlin from ..tools import get_data_dir, UMAKE class KotlinInContainer(ContainerTests, test_kotlin.KotlinTests): """This will test Kotlin integration inside a container""" def setUp(self): self.hosts = {443: ["api.github.com", "github.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'kotlin') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "kotlin", "kotlin-lang") def test_install_with_changed_download_page(self): """Installing Kotlin should fail if the download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "api.github.com", "repos", "Jetbrains", "kotlin", "releases", "latest") umake_command = self.command('{} kotlin'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.path_exists(self.exec_path)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_web.py0000664000000000000000000000472413013560574017155 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for web category""" from . import ContainerTests import os from ..large import test_web from ..tools import get_data_dir, UMAKE class FirefoxDevContainer(ContainerTests, test_web.FirefoxDevTests): """This will test the Firefox dev integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["www.mozilla.org"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "web", "firefox-dev") def test_install_with_changed_download_page(self): """Installing firefox developer should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.mozilla.org", "en-US", "firefox", "developer", "all") umake_command = self.command('{} web firefox-dev'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(os.path.join(self.binary_dir, self.desktop_filename.split('.')[0]))) class VisualStudioCodeInContainer(ContainerTests, test_web.VisualStudioCodeTest): """This will test the Visual Studio Code integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["code.visualstudio.com"], 80: ["go.microsoft.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'vscode') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "web", "visual-studio-code") ubuntu-make-16.11.1ubuntu1/tests/medium/test_nodejs.py0000664000000000000000000000427313013560574017661 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for nodejs""" from . import ContainerTests import os import subprocess from ..large import test_nodejs from ..tools import UMAKE, spawn_process class NodejsInContainer(ContainerTests, test_nodejs.NodejsTests): """This will test the Nodejs integration inside a container""" def setUp(self): self.hosts = {443: ["nodejs.org"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "nodejs", "nodejs-lang") def test_existing_prefix(self): subprocess.check_output(self.command_as_list(['echo', '''"prefix = test" > ~/.npmrc'''])) self.child = spawn_process(self.command('{} nodejs'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") result = subprocess.check_output(self.command_as_list(['cat', '''~/.npmrc'''])) self.assertEqual(result.rstrip().decode(), 'prefix = test') def test_existing_npmrc(self): subprocess.check_output(self.command_as_list(['echo', '''"test = 123" > ~/.npmrc'''])) self.child = spawn_process(self.command('{} nodejs'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") result = subprocess.check_output(self.command_as_list(['cat', '''~/.npmrc'''])) self.assertEqual(result.decode(), 'test = 123\r\nprefix = ${HOME}/.npm_modules') ubuntu-make-16.11.1ubuntu1/tests/medium/test_dart.py0000664000000000000000000000327513013560574017332 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for dart""" from . import ContainerTests import os from ..large import test_dart from ..tools import get_data_dir, UMAKE class DartInContainer(ContainerTests, test_dart.DartEditorTests): """This will test the eclipse IDE integration inside a container""" def setUp(self): self.hosts = {443: ["api.dartlang.org", "storage.googleapis.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "dart", "dart-sdk") def test_install_with_changed_version_page(self): """Installing dart sdk should fail if version page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "api.dartlang.org", "index.html") umake_command = self.command('{} dart'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_games.py0000664000000000000000000000650013013560574017466 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for games framework""" from . import ContainerTests import os from ..large import test_games from ..tools import get_data_dir, UMAKE class StencylInContainer(ContainerTests, test_games.StencylTests): """This will test the Stencyl editor inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {80: ["www.stencyl.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'stencyl') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "games", "stencyl") class Unity3DInContainer(ContainerTests, test_games.Unity3DTests): """This will test the Unity 3D editor inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {80: ["forum.unity3d.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'unity3d') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "games", "unity3d") class TwineInContainer(ContainerTests, test_games.TwineTests): """This will test Twine inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {80: ["twinery.org"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "games", "twine") class SuperpowersInContainer(ContainerTests, test_games.SuperpowersTests): """This will test Superpowers inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["api.github.com", "github.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'superpowers') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "games", "superpowers") def test_install_with_changed_download_page(self): """Installing Superpowers should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "api.github.com", "repos", "superpowers", "superpowers-app", "releases", "latest") umake_command = self.command('{} games superpowers'.format(UMAKE)) self.bad_download_page_test(self.command(self.command_args), download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_scala.py0000664000000000000000000000237113013560574017457 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # Igor Vuk # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for scala""" from . import ContainerTests import os from ..large import test_scala class ScalaInContainer(ContainerTests, test_scala.ScalaTests): """This will test the Scala integration inside a container""" def setUp(self): self.hosts = {80: ["www.scala-lang.org"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'scala') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "scala", "scala-lang") ubuntu-make-16.11.1ubuntu1/tests/medium/test_rust.py0000664000000000000000000000601413013560574017367 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014-2015 Canonical # # Authors: # Didier Roche # Jared Ravetch # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for rust""" from . import ContainerTests import os import pexpect from ..large import test_rust from ..tools import get_data_dir, UMAKE, swap_file_and_restore, spawn_process class RustInContainer(ContainerTests, test_rust.RustTests): """This will test the Rust integration inside a container""" TEST_CHECKSUM_RUST_DATA = "2a0db6efe370a900491d9e9db13e53ffd00b01dcd8458486f9f3fc3177f96af3" def setUp(self): self.hosts = {443: ["www.rust-lang.org", "static.rust-lang.org"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "rust", "rust-lang") def test_install_with_changed_download_reference_page(self): """Installing Rust should fail if download reference page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.rust-lang.org", "en-US", "downloads.html") umake_command = self.command('{} rust'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.path_exists(self.exec_path)) def test_install_with_wrong_sha(self): """Installing Rust should fail if checksum is wrong""" # we only modify the amd64 sha as docker only run on it download_page_file_path = os.path.join(get_data_dir(), "server-content", "static.rust-lang.org", "dist", "rust-fake-x86_64-unknown-linux-gnu.tar.gz.sha256") with swap_file_and_restore(download_page_file_path) as content: with open(download_page_file_path, "w") as newfile: newfile.write(content.replace(self.TEST_CHECKSUM_RUST_DATA, "abcdef")) self.child = spawn_process(self.command('{} rust'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn([pexpect.EOF, "Corrupted download? Aborting."], timeout=self.TIMEOUT_INSTALL_PROGRESS, expect_warn=True) self.wait_and_close(exit_status=1) # we have nothing installed self.assertFalse(self.path_exists(self.exec_path)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_swift.py0000664000000000000000000000341313013560574017526 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for swift""" from . import ContainerTests import os from ..large import test_swift from ..tools import get_data_dir, UMAKE class SwiftInContainer(ContainerTests, test_swift.SwiftTests): """This will test the Swift integration inside a container""" def setUp(self): self.hosts = {443: ["swift.org"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'swift') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "swift", "swift-lang") def test_install_with_changed_download_page(self): """Installing swift ide should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "swift.org", "download", "index.html") umake_command = self.command('{} swift'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.is_in_path(self.exec_path)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_basics_cli.py0000664000000000000000000000223313013560574020464 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for basic CLI commands""" import os from ..large import test_basics_cli from . import ContainerTests class BasicCLIInContainer(ContainerTests, test_basics_cli.BasicCLI): """This will test the basic cli command class inside a container""" def setUp(self): # Reuse the Android Studio environment.(used in --help) self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() ubuntu-make-16.11.1ubuntu1/tests/medium/test_ide.py0000664000000000000000000005567113013560574017150 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # Tin Tvrtković # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for ides""" from . import ContainerTests import os import pexpect from ..large import test_ide from ..tools import get_data_dir, swap_file_and_restore, UMAKE, spawn_process class EclipseJavaIDEInContainer(ContainerTests, test_ide.EclipseJavaIDETests): """This will test the eclipse IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["www.eclipse.org"]} # we reuse the android-studio repo self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.eclipse.org", "technology", "epp", "downloads", "release", "version", "point_release", "eclipse-java-linux-gtk-x86_64.tar.gz.sha512") def test_install_with_changed_download_page(self): """Installing eclipse ide should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.eclipse.org", "downloads", "eclipse-packages", "index.html") self.bad_download_page_test(self.command(self.command_args), download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) def test_install_with_changed_checksum_page(self): """Installing eclipse ide should fail if checksum link is unparseable""" self.bad_download_page_test(self.command(self.command_args), self.bad_download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) class EclipseJEEIDEInContainer(ContainerTests, test_ide.EclipseJEEIDETests): """This will test the eclipse IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["www.eclipse.org"]} # we reuse the android-studio repo self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse-jee") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.eclipse.org", "technology", "epp", "downloads", "release", "version", "point_release", "eclipse-jee-linux-gtk-x86_64.tar.gz.sha512") class EclipsePHPIDEInContainer(ContainerTests, test_ide.EclipsePHPIDETests): """This will test the eclipse IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["www.eclipse.org"]} # we reuse the android-studio repo self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse-php") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.eclipse.org", "technology", "epp", "downloads", "release", "version", "point_release", "eclipse-php-linux-gtk-x86_64.tar.gz.sha512") class EclipseCPPIDEInContainer(ContainerTests, test_ide.EclipseCPPIDETests): """This will test the eclipse IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["www.eclipse.org"]} # we reuse the android-studio repo self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "eclipse-cpp") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.eclipse.org", "technology", "epp", "downloads", "release", "version", "point_release", "eclipse-cpp-linux-gtk-x86_64.tar.gz.sha512") class IdeaIDEInContainer(ContainerTests, test_ide.IdeaIDETests): """This will test the Idea IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} # we reuse the android-studio repo self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "idea") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=IIC") # This actually tests the code in BaseJetBrains def test_install_with_changed_download_page(self): """Installing IntelliJ Idea should fail if download page has changed""" self.bad_download_page_test(self.command(self.command_args), self.bad_download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) class IdeaUltimateIDEInContainer(ContainerTests, test_ide.IdeaUltimateIDETests): """This will test the Idea Ultimate IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} # we reuse the android-studio repo self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "idea-ultimate") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=IIU") class PyCharmIDEInContainer(ContainerTests, test_ide.PyCharmIDETests): """This will test the PyCharm IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "pycharm") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=PCC") class PyCharmEducationalIDEInContainer(ContainerTests, test_ide.PyCharmEducationalIDETests): """This will test the PyCharm Educational IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "pycharm-educational") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=PCE") class PyCharmProfessionalIDEInContainer(ContainerTests, test_ide.PyCharmProfessionalIDETests): """This will test the PyCharm Professional IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "pycharm-professional") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=PCP") class RubyMineIDEInContainer(ContainerTests, test_ide.RubyMineIDETests): """This will test the RubyMine IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'rubymine') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "rubymine") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=RM") class WebStormIDEInContainer(ContainerTests, test_ide.WebStormIDETests): """This will test the WebStorm IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "webstorm") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=WS") class CLionIDEInContainer(ContainerTests, test_ide.CLionIDETests): """This will test the CLion IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "clion") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=CL") class DataGripIDEInContainer(ContainerTests, test_ide.DataGripIDETests): """This will test the DataGrip IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "datagrip") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=DG") class PhpStormIDEInContainer(ContainerTests, test_ide.PhpStormIDETests): """This will test the PhpStorm IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["data.services.jetbrains.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "phpstorm") self.bad_download_page_file_path = os.path.join(get_data_dir(), "server-content", "data.services.jetbrains.com", "products", "releases?code=PS") class ArduinoIDEInContainer(ContainerTests, test_ide.ArduinoIDETests): """This will test the Arduino IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {80: ["www.arduino.cc"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'arduino') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "arduino") def test_install_with_changed_download_page(self): """Installing arduino ide should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.arduino.cc", "en", "Main", "Software") umake_command = self.command('{} ide arduino'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) def test_install_with_changed_checksum_page(self): """Installing arduino ide should fail if checksum link is unparseable""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "www.arduino.cc", "checksums.md5sum.txt") umake_command = self.command('{} ide arduino'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) class BaseNetBeansInContainer(ContainerTests, test_ide.BaseNetBeansTests): """This will test the NetBeans IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 TEST_CHECKSUM_NETBEANS_DATA = "1e07ec8775939ba6d35731831bdb7bf0" def setUp(self): self.hosts = {80: ["download.netbeans.org"], 443: ["netbeans.org"]} # Reuse the Android Studio environment. self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "netbeans") def test_install_with_changed_download_page(self): """Installing NetBeans ide should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "netbeans.org", "downloads", "zip.html") umake_command = self.command('{} ide netbeans'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) def test_install_with_changed_download_reference_page(self): """Installing NetBeans ide should fail if download reference page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "netbeans.org", "images_www", "v6", "download", "8.0.42", "final", "js", "files.js") umake_command = self.command('{} ide netbeans'.format(UMAKE)) self.bad_download_page_test(umake_command, download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) def test_install_with_changed_checksum_page(self): """Installing NetBeans ide should fail if checksum link is wrong""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "netbeans.org", "images_www", "v6", "download", "8.0.42", "final", "js", "files.js") with swap_file_and_restore(download_page_file_path) as content: with open(download_page_file_path, "w") as newfile: newfile.write(content.replace(self.TEST_CHECKSUM_NETBEANS_DATA, "abcdef")) self.child = spawn_process(self.command('{} ide netbeans'.format(UMAKE))) self.expect_and_no_warn("Choose installation path: {}".format(self.installed_path)) self.child.sendline("") self.expect_and_no_warn([pexpect.EOF, "Corrupted download? Aborting."], timeout=self.TIMEOUT_INSTALL_PROGRESS, expect_warn=True) self.wait_and_close(exit_status=1) # we have nothing installed self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) class VisualStudioCodeInContainer(ContainerTests, test_ide.VisualStudioCodeTest): """This will test the Visual Studio Code integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["code.visualstudio.com"], 80: ["go.microsoft.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'vscode') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "visual-studio-code") class LightTableInContainer(ContainerTests, test_ide.LightTableTest): """This will test the LightTable integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["api.github.com", "github.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'LightTable') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "lighttable") def test_install_with_changed_download_page(self): """Installing LightTable should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "api.github.com", "repos", "LightTable", "LightTable", "releases", "latest") umake_command = self.command('{} ide lighttable'.format(UMAKE)) self.bad_download_page_test(self.command(self.command_args), download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) class AtomInContainer(ContainerTests, test_ide.AtomTest): """This will test the Atom integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["api.github.com", "github.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'Atom') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "atom") def test_install_with_changed_download_page(self): """Installing LightTable should fail if download page has significantly changed""" download_page_file_path = os.path.join(get_data_dir(), "server-content", "api.github.com", "repos", "Atom", "Atom", "releases", "latest") umake_command = self.command('{} ide atom'.format(UMAKE)) self.bad_download_page_test(self.command(self.command_args), download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) class SublimeTextInContainer(ContainerTests, test_ide.SublimeTextTests): """This will test the Sublime Text integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["sublimetext.com", "download.sublimetext.com"]} super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "sublime-text") class SpringToolsSuiteInContainer(ContainerTests, test_ide.SpringToolsSuiteTest): """This will test Spring Tools Suite IDE integration inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ['spring.io'], 80: ['dist.springsource.com']} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'eclipse') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "ide", "spring-tools-suite") def test_install_with_changed_download_page(self): """Installing STS should fail if download page has significantly changed""" return # framework disabled download_page_file_path = os.path.join(get_data_dir(), "server-content", "spring.io", "tools", "sts", "all") umake_command = self.command('{} ide spring-tools-suite'.format(UMAKE)) self.bad_download_page_test(self.command(self.command_args), download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) def test_install_with_changed_checksum_page(self): """Installing STS should fail if checksum link is unparseable""" return # framework disabled download_page_file_path = os.path.join(get_data_dir(), 'server-content', 'dist.springsource.com', 'release', 'STS', '3.7.2.RELEASE', 'dist', 'e4.5', 'spring-tool-suite-3.7.2.RELEASE-e4.5.1-linux-gtk-x86_64.tar.gz.sha1') self.bad_download_page_test(self.command(self.command_args), download_page_file_path) self.assertFalse(self.launcher_exists_and_is_pinned(self.desktop_filename)) self.assertFalse(self.is_in_path(self.exec_link)) ubuntu-make-16.11.1ubuntu1/tests/medium/test_android.py0000664000000000000000000000443013013560574020012 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for android frameworks in container""" from . import ContainerTests import os from ..large import test_android class AndroidStudioInContainer(ContainerTests, test_android.AndroidStudioTests): """This will install Android Studio inside a container""" TIMEOUT_START = 20 TIMEOUT_STOP = 10 def setUp(self): self.hosts = {443: ["developer.android.com", "dl.google.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "android", "android-studio") class AndroidSDKInContainer(ContainerTests, test_android.AndroidSDKTests): """This will install Android SDK inside a container""" def setUp(self): self.hosts = {443: ["developer.android.com", "dl.google.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "android", "android-sdk") class AndroidNDKInContainer(ContainerTests, test_android.AndroidNDKTests): """This will install Android NDK inside a container""" def setUp(self): self.hosts = {80: ["dl.google.com"], 443: ["developer.android.com"]} self.apt_repo_override_path = os.path.join(self.APT_FAKE_REPO_PATH, 'android') super().setUp() # override with container path self.installed_path = os.path.join(self.install_base_path, "android", "android-ndk") ubuntu-make-16.11.1ubuntu1/tests/small/0000775000000000000000000000000013013560574014610 5ustar ubuntu-make-16.11.1ubuntu1/tests/small/__init__.py0000664000000000000000000001133313013560574016722 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2016 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Some common tools between small tests""" import apt import os import shutil import stat import tempfile from ..tools import get_data_dir, LoggedTestCase, manipulate_path_env from unittest.mock import Mock from umake import tools class DpkgAptSetup(LoggedTestCase): """This parent class is there to setup and teardown a dpkg chroot test environment""" @classmethod def setUpClass(cls): super().setUpClass() apt.apt_pkg.config.set("Dir::Cache::pkgcache", "") apt.apt_pkg.config.set("Dir::Cache::srcpkgcache", "") apt.apt_pkg.config.clear("APT::Update::Post-Invoke") apt.apt_pkg.config.clear("APT::Update::Post-Invoke-Success") apt.apt_pkg.config.clear("DPkg::Post-Invoke") cls.apt_package_dir = os.path.join(get_data_dir(), "apt") cls.apt_status_dir = os.path.join(cls.apt_package_dir, "states") def setUp(self): super().setUp() self.chroot_path = tempfile.mkdtemp() # create the fake dpkg wrapper os.makedirs(os.path.join(self.chroot_path, "usr", "bin")) self.dpkg = os.path.join(self.chroot_path, "usr", "bin", "dpkg") with open(self.dpkg, "w") as f: # Don't nest fakeroot calls when having some dpkg hook scripts f.write("#!/bin/sh\nprependfakeroot=''\nif [ -z \"$FAKEROOTKEY\" ]; then\nprependfakeroot=fakeroot\nfi\n " "$prependfakeroot /usr/bin/dpkg --root={root} --force-not-root --force-bad-path " "--log={root}/var/log/dpkg.log \"$@\"".format(root=self.chroot_path)) st = os.stat(self.dpkg) os.chmod(self.dpkg, st.st_mode | stat.S_IEXEC) # for arch cache support tools._current_arch = None tools._foreign_arch = None manipulate_path_env(os.path.dirname(self.dpkg)) # apt requirements apt_etc = os.path.join(self.chroot_path, 'etc', 'apt') os.makedirs(apt_etc) os.makedirs(os.path.join(self.chroot_path, 'var', 'log', 'apt')) with open(os.path.join(apt_etc, 'sources.list'), 'w') as f: f.write('deb [trusted=yes] file:{} /'.format(self.apt_package_dir)) # dpkg requirements dpkg_dir = os.path.join(self.chroot_path, 'var', 'lib', 'dpkg') os.makedirs(dpkg_dir) os.mkdir(os.path.join(os.path.join(dpkg_dir, 'info'))) os.mkdir(os.path.join(os.path.join(dpkg_dir, 'triggers'))) os.mkdir(os.path.join(os.path.join(dpkg_dir, 'updates'))) open(os.path.join(dpkg_dir, 'status'), 'w').close() open(os.path.join(dpkg_dir, 'available'), 'w').close() self.dpkg_dir = dpkg_dir cache = apt.Cache(rootdir=self.chroot_path) apt.apt_pkg.config.set("Dir::Bin::dpkg", self.dpkg) # must be called after initializing the rootdir cache cache.update() cache.open() if hasattr(self, "handler"): self.handler.cache = cache self.done_callback = Mock() self._saved_seteuid_fn = os.seteuid self._saved_setegid_fn = os.setegid self._saved_geteuid_fn = os.geteuid self._saved_getenv = os.getenv self.user_uid, self.user_gid = (4242, 4242) os.seteuid = Mock() os.setegid = Mock() os.geteuid = Mock() os.geteuid.return_value = self.user_uid os.getenv = Mock(side_effect=self._mock_get_env) def tearDown(self): # remove arch cache support manipulate_path_env(os.path.dirname(self.dpkg), remove=True) tools._current_arch = None tools._foreign_arch = None shutil.rmtree(self.chroot_path) os.seteuid = self._saved_seteuid_fn os.setegid = self._saved_setegid_fn os.geteuid = self._saved_geteuid_fn os.getenv = self._saved_getenv super().tearDown() def _mock_get_env(self, env, default=None): if os.geteuid() == 0: if env == "SUDO_UID": return str(self.user_uid) elif env == "SUDO_GID": return str(self.user_gid) return self._saved_getenv(env) ubuntu-make-16.11.1ubuntu1/tests/small/test_tools.py0000664000000000000000000015223413013560574017370 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # This program is distributed in he 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests the various umake tools""" from concurrent import futures from contextlib import contextmanager, suppress from gi.repository import GLib import os import shutil import subprocess import stat import sys import tempfile from textwrap import dedent from time import time import threading from . import DpkgAptSetup from ..tools import change_xdg_path, get_data_dir, LoggedTestCase, INSTALL_DIR from umake import settings, tools from umake.tools import ConfigHandler, Singleton, get_current_arch, get_foreign_archs, get_current_ubuntu_version,\ create_launcher, launcher_exists_and_is_pinned, launcher_exists, get_icon_path, get_launcher_path, copy_icon,\ add_exec_link from unittest.mock import patch, Mock class TestConfigHandler(LoggedTestCase): """This will test the config handler using xdg dirs""" def setUp(self): super().setUp() self.config_dir = tempfile.mkdtemp() change_xdg_path('XDG_CONFIG_HOME', self.config_dir) def tearDown(self): # remove caching Singleton._instances = {} change_xdg_path('XDG_CONFIG_HOME', remove=True) shutil.rmtree(self.config_dir) super().tearDown() def config_dir_for_name(self, name): """Return the config dir for this name""" return os.path.join(get_data_dir(), 'configs', name) def test_singleton(self): """Ensure we are delivering a singleton for TestConfigHandler""" config1 = ConfigHandler() config2 = ConfigHandler() self.assertEqual(config1, config2) def test_load_config(self): """Valid config loads correct content""" change_xdg_path('XDG_CONFIG_HOME', self.config_dir_for_name("valid")) self.assertEqual(ConfigHandler().config, {'frameworks': { 'category-a': { 'framework-a': {'path': '/home/didrocks/quickly/ubuntu-make/adt-eclipse'}, 'framework-b': {'path': '/home/didrocks/foo/bar/android-studio'} } }}) def test_load_no_config(self): """No existing file gives an empty result""" change_xdg_path('XDG_CONFIG_HOME', self.config_dir_for_name("foo")) self.assertEqual(ConfigHandler().config, {}) def test_load_invalid_config(self): """Existing invalid file gives an empty result""" change_xdg_path('XDG_CONFIG_HOME', self.config_dir_for_name("invalid")) self.assertEqual(ConfigHandler().config, {}) self.expect_warn_error = True def test_save_new_config(self): """Save a new config in a vanilla directory""" content = {'foo': 'bar'} ConfigHandler().config = content self.assertEqual(ConfigHandler().config, content) with open(os.path.join(self.config_dir, settings.CONFIG_FILENAME)) as f: self.assertEqual(f.read(), 'foo: bar\n') def test_save_config_without_xdg_dir(self): """Save a new config file with an unexisting directory""" os.removedirs(self.config_dir) self.test_save_new_config() def test_save_config_existing(self): """Replace an existing config with a new one""" shutil.copy(os.path.join(self.config_dir_for_name('valid'), settings.CONFIG_FILENAME), self.config_dir) content = {'foo': 'bar'} ConfigHandler().config = content self.assertEqual(ConfigHandler().config, content) with open(os.path.join(self.config_dir, settings.CONFIG_FILENAME)) as f: self.assertEqual(f.read(), 'foo: bar\n') def test_dont_create_file_without_assignment(self): """We don't create any file without an assignment""" ConfigHandler() self.assertEqual(len(os.listdir(self.config_dir)), 0) def test_transition_old_config(self): """Transition udtc old config to new umake one""" with tempfile.TemporaryDirectory() as tmpdirname: shutil.copy(os.path.join(self.config_dir_for_name("old"), "udtc"), tmpdirname) change_xdg_path('XDG_CONFIG_HOME', tmpdirname) self.assertEqual(ConfigHandler().config, {'frameworks': { 'category-a': { 'framework-a': {'path': '/home/didrocks/quickly/ubuntu-make/adt-eclipse'}, 'framework-b': {'path': '/home/didrocks/foo/bar/android-studio'} } }}) # file has been renamed self.assertTrue(os.path.exists(os.path.join(tmpdirname, "umake")), "New umake config file exists") self.assertFalse(os.path.exists(os.path.join(tmpdirname, "udtc")), "Old udtc config file is removed") class TestGetUbuntuVersion(LoggedTestCase): def setUp(self): """Reset previously cached values""" super().setUp() tools._version = None def tearDown(self): """Reset cached values""" tools._version = None super().tearDown() def get_lsb_release_filepath(self, name): return os.path.join(get_data_dir(), 'lsb_releases', name) @patch("umake.tools.settings") def test_get_current_ubuntu_version(self, settings_module): """Current ubuntu version is reported from our lsb_release local file""" settings_module.LSB_RELEASE_FILE = self.get_lsb_release_filepath("valid") self.assertEqual(get_current_ubuntu_version(), '14.04') @patch("umake.tools.settings") def test_get_current_ubuntu_version_invalid(self, settings_module): """Raise an error when parsing an invalid lsb release file""" settings_module.LSB_RELEASE_FILE = self.get_lsb_release_filepath("invalid") self.assertRaises(BaseException, get_current_ubuntu_version) self.expect_warn_error = True @patch("umake.tools.settings") def test_get_current_ubuntu_version_no_lsb_release(self, settings_module): """Raise an error when there is no lsb release file""" settings_module.LSB_RELEASE_FILE = self.get_lsb_release_filepath("notexist") self.assertRaises(BaseException, get_current_ubuntu_version) self.expect_warn_error = True class TestCompletion(LoggedTestCase): def setUp(self): super().setUp() self.initial_env = os.environ.copy() def tearDown(self): # restore original environment. Do not use the dict copy which erases the object and doesn't have the magical # _Environ which setenv() for subprocess os.environ.clear() os.environ.update(self.initial_env) super().tearDown() def test_in_completion_mode(self): """We return if we are in completion mode""" os.environ["_ARGCOMPLETE"] = "1" self.assertTrue(tools.is_completion_mode()) def test_not_incompletion_mode(self): """We are not in completion mode by default""" self.assertFalse(tools.is_completion_mode()) class TestArchVersion(DpkgAptSetup): def setUp(self): """Reset previously cached values""" super().setUp() tools._current_arch = None tools._foreign_arch = None def tearDown(self): """Reset cached values""" tools._current_arch = None tools._foreign_arch = None super().tearDown() def dpkg_error(self, *args, **kwargs): """Simulate a dpkg failure""" raise subprocess.CalledProcessError("dpkg failure", cmd="dpkg") def test_get_current_arch(self): """Current arch is reported""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.return_value = "fooarch" self.assertEqual(get_current_arch(), "fooarch") def test_get_current_arch_twice(self): """Current arch is reported twice and the same""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.return_value = "fooarch" self.assertEqual(get_current_arch(), "fooarch") self.assertEqual(get_current_arch(), "fooarch") self.assertEquals(subprocess_mock.check_output.call_count, 1, "We cache older value") def test_get_current_arch_no_dpkg(self): """Assert an error if dpkg exit with an error""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.side_effect = self.dpkg_error self.assertRaises(subprocess.CalledProcessError, get_current_arch) def test_get_foreign_arch(self): """Get current foreign arch (one)""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.return_value = "fooarch" self.assertEqual(get_foreign_archs(), ["fooarch"]) def test_get_foreign_archs(self): """Get current foreign arch (multiple)""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.return_value = "fooarch\nbararch\nbazarch" self.assertEqual(get_foreign_archs(), ["fooarch", "bararch", "bazarch"]) def test_get_foreign_archs_error(self): """Get current foreign arch raises an exception if dpkg is in error""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.side_effect = self.dpkg_error self.assertRaises(subprocess.CalledProcessError, get_foreign_archs) def test_add_new_foreign_arch(self): """Add a new foreign arch and check that we can retrieve it (cache invalidated)""" tools.add_foreign_arch("foo") self.assertEqual(get_foreign_archs(), ["foo"]) def test_add_foreign_arch_already_in(self): """Add a foreign arch which was already there should be a noop""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.return_value = "foo" subprocess_mock.call.side_effect = subprocess.call tools.add_foreign_arch("foo") self.assertFalse(subprocess_mock.call.called) def test_add_current_arch(self): """Add the current arch should be a noop""" tools._current_arch = "foo" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.call.side_effect = subprocess.call tools.add_foreign_arch("foo") def test_add_new_foreign_arch_fail(self): """Add a new foreign arch, but failing should raise an exception""" with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.call.return_value = 1 self.assertRaises(BaseException, tools.add_foreign_arch, "foo") class TestToolsThreads(LoggedTestCase): """Test main loop threading helpers""" def setUp(self): super().setUp() self.mainloop_object = tools.MainLoop() self.mainloop_thread = None self.function_thread = None self.saved_stderr = sys.stderr def tearDown(self): Singleton._instances = {} sys.stderr = self.saved_stderr super().tearDown() def patch_stderr(self): class writer(object): def write(self, data): print(data) sys.stderr = writer() # function that will complete once the mainloop is started def wait_for_mainloop_function(self): timeout_time = time() + 5 while not self.mainloop_object.mainloop.is_running(): if time() > timeout_time: raise(BaseException("Mainloop not started in 5 seconds")) def wait_for_mainloop_shutdown(self): timeout_time = time() + 5 while self.mainloop_object.mainloop.is_running(): if time() > timeout_time: raise(BaseException("Mainloop not stopped in 5 seconds")) def get_mainloop_thread(self): self.mainloop_thread = threading.current_thread().ident def start_glib_mainloop(self): # quit after 5 seconds if nothing made the mainloop to end GLib.timeout_add_seconds(5, self.mainloop_object.mainloop.quit) GLib.idle_add(self.get_mainloop_thread) self.mainloop_object.run() @patch("umake.tools.sys") def test_run_function_in_mainloop_thread(self, mocksys): """Decorated mainloop thread functions are really running in that thread""" # function supposed to run in the mainloop thread @tools.MainLoop.in_mainloop_thread def _function_in_mainloop_thread(future): self.function_thread = threading.current_thread().ident self.mainloop_object.quit() executor = futures.ThreadPoolExecutor(max_workers=1) future = executor.submit(self.wait_for_mainloop_function) future.add_done_callback(_function_in_mainloop_thread) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() # mainloop and thread were started self.assertIsNotNone(self.mainloop_thread) self.assertIsNotNone(self.function_thread) self.assertEqual(self.mainloop_thread, self.function_thread) @patch("umake.tools.sys") def test_run_function_not_in_mainloop_thread(self, mocksys): """Non decorated callback functions are not running in the mainloop thread""" # function not supposed to run in the mainloop thread def _function_not_in_mainloop_thread(future): self.function_thread = threading.current_thread().ident self.mainloop_object.quit(raise_exception=False) # as we don't run that from the mainloop executor = futures.ThreadPoolExecutor(max_workers=1) future = executor.submit(self.wait_for_mainloop_function) future.add_done_callback(_function_not_in_mainloop_thread) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() # mainloop and thread were started self.assertIsNotNone(self.mainloop_thread) self.assertIsNotNone(self.function_thread) self.assertNotEqual(self.mainloop_thread, self.function_thread) def test_singleton(self): """Ensure we are delivering a singleton for RequirementsHandler""" second = tools.MainLoop() self.assertEqual(self.mainloop_object, second) def test_mainloop_run(self): """We effectively executes the mainloop""" with patch.object(self.mainloop_object, "mainloop") as mockmainloop: self.mainloop_object.run() self.assertTrue(mockmainloop.run.called) @patch("umake.tools.sys") def test_mainloop_quit(self, mocksys): """We quit the process""" def _quit_ignoring_exception(): self.mainloop_object.quit(raise_exception=False) # as we don't run that from the mainloop GLib.idle_add(_quit_ignoring_exception) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() mocksys.exit.assert_called_once_with(0) @patch("umake.tools.sys") def test_mainloop_quit_with_exit_value(self, mocksys): """We quit the process with a return code""" def _quit_ignoring_exception(): self.mainloop_object.quit(42, raise_exception=False) # as we don't run that from the mainloop GLib.idle_add(_quit_ignoring_exception) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() mocksys.exit.assert_called_once_with(42) @patch("umake.tools.sys") def test_unhandled_exception_in_mainloop_thead_exit(self, mocksys): """We quit the process in error for any unhandled exception, logging it""" @tools.MainLoop.in_mainloop_thread def _function_raising_exception(): raise BaseException("foo bar") _function_raising_exception() self.patch_stderr() self.start_glib_mainloop() self.wait_for_mainloop_shutdown() mocksys.exit.assert_called_once_with(1) self.expect_warn_error = True class TestLauncherIcons(LoggedTestCase): """Test module for launcher icons handling""" @classmethod def setUpClass(cls): super().setUpClass() cls.server_dir = os.path.join(get_data_dir(), "server-content") def setUp(self): super().setUp() self.local_dir = tempfile.mkdtemp() os.mkdir(os.path.join(self.local_dir, "applications")) os.mkdir(os.path.join(self.local_dir, "icons")) change_xdg_path('XDG_DATA_HOME', self.local_dir) self.current_desktop = os.environ.get("XDG_CURRENT_DESKTOP") os.environ["XDG_CURRENT_DESKTOP"] = "Unity" def tearDown(self): change_xdg_path('XDG_DATA_HOME', remove=True) shutil.rmtree(self.local_dir) if self.current_desktop: os.environ["XDG_CURRENT_DESKTOP"] = self.current_desktop super().tearDown() def get_generic_desktop_content(self): """Return a generic desktop content to win spaces""" return dedent("""\ [Desktop Entry] Version=1.0 Type=Application Name=Android Studio Icon=/home/didrocks/{install_dir}/android-studio/bin/studio.png Exec="/home/didrocks/{install_dir}/android-studio/bin/studio.sh" %f Comment=Develop with pleasure! Categories=Development;IDE; Terminal=false StartupWMClass=jetbrains-android-studio """.format(install_dir=INSTALL_DIR)) def write_desktop_file(self, filename): """Write a dummy filename to the applications dir and return filepath""" result_file = os.path.join(self.local_dir, "applications", filename) with open(result_file, 'w') as f: f.write("Foo Bar Baz") return result_file @patch("umake.tools.Gio.Settings") def test_can_install(self, SettingsMock): """Install a basic launcher, default case with unity://running""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "unity://running-apps"] create_launcher("foo.desktop", self.get_generic_desktop_content()) self.assertTrue(SettingsMock.list_schemas.called) SettingsMock.return_value.get_strv.assert_called_with("favorites") SettingsMock.return_value.set_strv.assert_called_with("favorites", ["application://bar.desktop", "application://foo.desktop", "unity://running-apps"]) self.assertTrue(os.path.exists(get_launcher_path("foo.desktop"))) self.assertEqual(open(get_launcher_path("foo.desktop")).read(), self.get_generic_desktop_content()) @patch("umake.tools.Gio.Settings") def test_can_update_launcher(self, SettingsMock): """Update a launcher file""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "unity://running-apps"] create_launcher("foo.desktop", self.get_generic_desktop_content()) new_content = dedent("""\ [Desktop Entry] Version=1.0 Type=Application Name=Android Studio 2 Icon=/home/didrocks/{install_dir}/android-studio/bin/idea2.png Exec="/home/didrocks/{install_dir}/android-studio/bin/studio2.sh" %f Comment=Develop with pleasure! Categories=Development;IDE; Terminal=false StartupWMClass=jetbrains-android-studio """.format(install_dir=INSTALL_DIR)) create_launcher("foo.desktop", new_content) self.assertTrue(os.path.exists(get_launcher_path("foo.desktop"))) self.assertEqual(open(get_launcher_path("foo.desktop")).read(), new_content) @patch("umake.tools.Gio.Settings") def test_can_install_without_unity_running(self, SettingsMock): """Install a basic launcher icon, without a running apps entry (so will be last)""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "application://baz.desktop"] create_launcher("foo.desktop", self.get_generic_desktop_content()) self.assertTrue(SettingsMock.list_schemas.called) SettingsMock.return_value.set_strv.assert_called_with("favorites", ["application://bar.desktop", "application://baz.desktop", "application://foo.desktop"]) @patch("umake.tools.Gio.Settings") def test_can_install_already_in_launcher(self, SettingsMock): """A file listed in launcher still install the files, but the entry isn't changed""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "application://foo.desktop", "unity://running-apps"] create_launcher("foo.desktop", self.get_generic_desktop_content()) self.assertFalse(SettingsMock.return_value.set_strv.called) self.assertTrue(os.path.exists(get_launcher_path("foo.desktop"))) @patch("umake.tools.Gio.Settings") def test_install_no_schema_file(self, SettingsMock): """No schema file still installs the file""" SettingsMock.list_schemas.return_value = ["foo", "bar", "baz"] create_launcher("foo.desktop", self.get_generic_desktop_content()) self.assertFalse(SettingsMock.return_value.get_strv.called) self.assertFalse(SettingsMock.return_value.set_strv.called) self.assertTrue(os.path.exists(get_launcher_path("foo.desktop"))) @patch("umake.tools.Gio.Settings") def test_already_existing_file_different_content(self, SettingsMock): """A file with a different file content already exists and is updated""" SettingsMock.list_schemas.return_value = ["foo", "bar", "baz"] result_file = self.write_desktop_file("foo.desktop") create_launcher("foo.desktop", self.get_generic_desktop_content()) self.assertEqual(open(result_file).read(), self.get_generic_desktop_content()) @patch("umake.tools.Gio.Settings") def test_create_launcher_without_xdg_dir(self, SettingsMock): """Save a new launcher in an unexisting directory""" shutil.rmtree(self.local_dir) SettingsMock.list_schemas.return_value = ["foo", "bar", "baz"] create_launcher("foo.desktop", self.get_generic_desktop_content()) self.assertTrue(os.path.exists(get_launcher_path("foo.desktop"))) def test_desktop_file_exists(self): """Launcher exists""" self.write_desktop_file("foo.desktop") self.assertTrue(launcher_exists("foo.desktop")) def test_desktop_file_doesnt_exist(self): """Launcher file doesn't exists""" self.assertFalse(launcher_exists("foo.desktop")) @patch("umake.tools.Gio.Settings") def test_launcher_exists_and_is_pinned(self, SettingsMock): """Launcher exists and is pinned if the file exists and is in favorites list""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "application://foo.desktop", "unity://running-apps"] self.write_desktop_file("foo.desktop") self.assertTrue(launcher_exists_and_is_pinned("foo.desktop")) @patch("umake.tools.Gio.Settings") def test_launcher_isnt_pinned(self, SettingsMock): """Launcher doesn't exists and is pinned if the file exists but not in favorites list""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "unity://running-apps"] self.write_desktop_file("foo.desktop") self.assertFalse(launcher_exists_and_is_pinned("foo.desktop")) @patch("umake.tools.Gio.Settings") def test_launcher_exists_but_isnt_pinned_in_none_unity(self, SettingsMock): """Launcher exists return True if file exists, not pinned but not in Unity""" os.environ["XDG_CURRENT_DESKTOP"] = "FOOenv" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "unity://running-apps"] self.write_desktop_file("foo.desktop") self.assertTrue(launcher_exists_and_is_pinned("foo.desktop")) @patch("umake.tools.Gio.Settings") def test_launcher_exists_but_not_schema_in_none_unity(self, SettingsMock): """Launcher exists return True if file exists, even if Unity schema isn't installed""" os.environ["XDG_CURRENT_DESKTOP"] = "FOOenv" SettingsMock.list_schemas.return_value = ["foo", "bar", "baz"] self.write_desktop_file("foo.desktop") self.assertTrue(launcher_exists_and_is_pinned("foo.desktop")) @patch("umake.tools.Gio.Settings") def test_launcher_exists_but_not_schema_in_unity(self, SettingsMock): """Launcher exists return False if file exists, but no Unity schema installed""" SettingsMock.list_schemas.return_value = ["foo", "bar", "baz"] self.write_desktop_file("foo.desktop") self.assertFalse(launcher_exists_and_is_pinned("foo.desktop")) @patch("umake.tools.Gio.Settings") def test_launcher_doesnt_exists_but_pinned(self, SettingsMock): """Launcher doesn't exist if no file, even if pinned""" SettingsMock.list_schemas.return_value = ["foo", "bar", "com.canonical.Unity.Launcher", "baz"] SettingsMock.return_value.get_strv.return_value = ["application://bar.desktop", "application://foo.desktop", "unity://running-apps"] self.assertFalse(launcher_exists_and_is_pinned("foo.desktop")) def test_can_copy_icon(self): """Copy a basic icon""" # we copy any file and treat it as an icon copy_icon(os.path.join(self.server_dir, "simplefile"), "foo.png") self.assertTrue(os.path.exists(get_icon_path("foo.png"))) self.assertEqual(open(os.path.join(self.server_dir, "simplefile")).read(), open(get_icon_path("foo.png")).read()) def test_can_update_icon(self): """Update a basic icon with a new content""" copy_icon(os.path.join(self.server_dir, "simplefile"), "foo.png") copy_icon(os.path.join(self.server_dir, "biggerfile"), "foo.png") self.assertTrue(os.path.exists(get_icon_path("foo.png"))) self.assertEqual(open(os.path.join(self.server_dir, "biggerfile")).read(), open(get_icon_path("foo.png")).read()) def test_can_copy_icon_with_glob(self): """Copy an icon with glob pattern matching""" # we copy any file and treat it as an icon copy_icon(os.path.join(self.server_dir, "sim*file"), "foo.png") self.assertTrue(os.path.exists(get_icon_path("foo.png"))) self.assertEqual(open(os.path.join(self.server_dir, "simplefile")).read(), open(get_icon_path("foo.png")).read()) def test_create_icon_without_xdg_dir(self): """Save a new icon in an unexisting directory""" shutil.rmtree(self.local_dir) copy_icon(os.path.join(self.server_dir, "simplefile"), "foo.png") self.assertTrue(os.path.exists(get_icon_path("foo.png"))) def test_get_icon_path(self): """Get correct launcher path""" self.assertEqual(get_icon_path("foo.png"), os.path.join(self.local_dir, "icons", "foo.png")) def test_get_launcher_path(self): """Get correct launcher path""" self.assertEqual(get_launcher_path("foo.desktop"), os.path.join(self.local_dir, "applications", "foo.desktop")) @patch("umake.tools.settings") def test_create_exec_path(self, settings_module): """Create link to the executable""" settings_module.DEFAULT_BINARY_LINK_PATH = os.path.join(self.local_dir, ".local", "share", "umake", "bin") add_exec_link(os.path.join(self.server_dir, "simplefile"), "foo") self.assertTrue(os.path.exists(os.path.join(settings_module.DEFAULT_BINARY_LINK_PATH, "foo"))) class TestMiscTools(LoggedTestCase): def test_get_application_desktop_file(self): """We return expect results with normal content""" self.assertEqual(tools.get_application_desktop_file(name="Name 1", icon_path="/to/icon/path", exec="/to/exec/path %f", comment="Comment for Name 1", categories="Cat1:Cat2"), dedent("""\ [Desktop Entry] Version=1.0 Type=Application Name=Name 1 Icon=/to/icon/path Exec=/to/exec/path %f Comment=Comment for Name 1 Categories=Cat1:Cat2 Terminal=false """)) def test_get_application_desktop_file_with_extra(self): """We return expect results with extra content""" self.assertEqual(tools.get_application_desktop_file(name="Name 1", icon_path="/to/icon/path", exec="/to/exec/path %f", comment="Comment for Name 1", categories="Cat1:Cat2", extra="Extra=extra1\nFoo=foo"), dedent("""\ [Desktop Entry] Version=1.0 Type=Application Name=Name 1 Icon=/to/icon/path Exec=/to/exec/path %f Comment=Comment for Name 1 Categories=Cat1:Cat2 Terminal=false Extra=extra1 Foo=foo """)) def test_get_application_desktop_file_all_empty(self): """We return expect results without any content""" self.assertEqual(tools.get_application_desktop_file(), dedent("""\ [Desktop Entry] Version=1.0 Type=Application Name= Icon= Exec= Comment= Categories= Terminal=false """)) def test_strip_tags(self): """We return strip tags from content""" self.assertEqual(tools.strip_tags("content content content contentcontent\n content" "\ncontent content"), "content content content contentcontent\n content\ncontent content") def test_strip_invalid_tags(self): """We return trip tags even if invalid""" self.assertEqual(tools.strip_tags("content content content contentcontent\n content" "\ncontent content"), "content content content contentcontent\n content\ncontent content") def test_strip_without_tags(self): """We return unmodified content if there is no tag""" self.assertEqual(tools.strip_tags("content content content contentcontent\n content" "\ncontent content"), "content content content contentcontent\n content\ncontent content") def test_raise_inputerror(self): def foo(): raise tools.InputError("Foo bar") self.assertRaises(tools.InputError, foo) def test_print_inputerror(self): self.assertEqual(str(tools.InputError("Foo bar")), "'Foo bar'") @patch("umake.tools.os") def test_switch_user_from_sudo(self, osmock): """Test switch user account from root to previous user under SUDO""" osmock.getenv.return_value = 1234 osmock.geteuid.return_value = 0 tools.switch_to_current_user() osmock.setegid.assert_called_once_with(1234) osmock.seteuid.assert_called_once_with(1234) @patch("umake.tools.os") def test_switch_user_from_non_sudo(self, osmock): """Test switch user from a non sudo command (non root), dosen't call anything""" osmock.getenv.return_value = 1234 osmock.geteuid.return_value = 1234 tools.switch_to_current_user() self.assertFalse(osmock.setegid.called) self.assertFalse(osmock.seteuid.called) self.assertFalse(osmock.getenv.called) @patch("umake.tools.os") def test_switch_user_from_root(self, osmock): """Test switch user from root, let it as root""" osmock.getenv.return_value = 0 osmock.geteuid.return_value = 0 tools.switch_to_current_user() osmock.setegid.assert_called_once_with(0) osmock.seteuid.assert_called_once_with(0) @patch("umake.tools.os") @patch("umake.tools.switch_to_current_user") def test_as_root(self, switch_to_current_usermock, osmock): """Switch as root when everything is permitted""" with tools.as_root(): osmock.seteuid.assert_called_once_with(0) osmock.setegid.assert_called_once_with(0) self.assertFalse(switch_to_current_usermock.called, "didn't switch to current user in context") self.assertTrue(switch_to_current_usermock.called, "switch back to user when exiting context") @patch("umake.tools.os") @patch("umake.tools.switch_to_current_user") def test_as_root_euid_perm_denied(self, switch_to_current_usermock, osmock): """Switch as root raise exception when euid permission is denied""" def raiseException(self): raise PermissionError("") osmock.seteuid.side_effect = raiseException exception_raised = False try: with tools.as_root(): pass except PermissionError: exception_raised = True self.assertTrue(exception_raised, "Permission Error was raised") self.assertTrue(switch_to_current_usermock.called, "switch back to user when exiting context") @patch("umake.tools.os") @patch("umake.tools.switch_to_current_user") def test_as_root_egid_perm_denied(self, switch_to_current_usermock, osmock): """Switch as root raise exception when egid permission is denied""" def raiseException(self): raise PermissionError("") osmock.setegid.side_effect = raiseException exception_raised = False try: with tools.as_root(): pass except PermissionError: exception_raised = True self.assertTrue(exception_raised, "Permission Error was raised") self.assertTrue(switch_to_current_usermock.called, "switch back to user when exiting context") @patch("umake.tools.os") @patch("umake.tools.switch_to_current_user") def test_as_root_with_lock(self, switch_to_current_usermock, osmock): """Ensure we don't try to switch as root before the lock is released""" def as_root_function(): with tools.as_root(): method_called_as_root() method_called_as_root = Mock() executor = futures.ThreadPoolExecutor(max_workers=1) # take main lock in that thread and start other one tools.root_lock.acquire() future = executor.submit(as_root_function) # we didn't get any root switch self.assertFalse(osmock.seteuid.called, "we didn't switch to root yet with seteuid") self.assertFalse(osmock.setegid.called, "we didn't switch to root yet with setegid") # release it tools.root_lock.release() # wait for the executor to finish in 1s and ensure that root was called future.result(1) osmock.seteuid.assert_called_once_with(0) osmock.setegid.assert_called_once_with(0) self.assertTrue(switch_to_current_usermock.called, "switch back to user when exiting context") class TestUserENV(LoggedTestCase): def setUp(self): super().setUp() self.orig_environ = os.environ.copy() self.local_dir = tempfile.mkdtemp() os.environ['SHELL'] = '/bin/bash' def tearDown(self): shutil.rmtree(self.local_dir) # restore original environment. Do not use the dict copy which erases the object and doesn't have the magical # _Environ which setenv() for subprocess os.environ.clear() os.environ.update(self.orig_environ) super().tearDown() @patch("umake.tools.os.path.expanduser") def test_add_env_to_user(self, expanderusermock): """Test that adding to user env appending to an existing .profile file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"FOOO": {"value": "bar"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=bar\n" in profile_content, profile_content) self.assertTrue("bar" in os.environ["FOOO"], os.environ["FOOO"]) @patch("umake.tools.os.path.expanduser") def test_add_env_to_user(self, expanderusermock): """Test that adding to user env a list concatenate them to an existing .profile file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"FOOO": {"value": ["bar", "baz"]}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=bar:baz\n" in profile_content, profile_content) self.assertTrue("bar" in os.environ["FOOO"], os.environ["FOOO"]) @patch("umake.tools.os.path.expanduser") def test_add_env_to_user_with_shell_zsh(self, expanderusermock): """Test that adding to user env appending to an existing .zprofile file""" os.environ['SHELL'] = '/bin/zsh' expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".zprofile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"FOOO": {"value": "bar"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=bar\n" in profile_content, profile_content) self.assertTrue("bar" in os.environ["FOOO"], os.environ["FOOO"]) @patch("umake.tools.os.path.expanduser") def test_add_env_to_user_keep(self, expanderusermock): """Test that adding to user env appending to an existing env""" os.environ["FOOO"] = "foo" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"FOOO": {"value": "bar"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=bar:$FOOO\n" in profile_content, profile_content) self.assertEqual(os.environ["FOOO"], "bar:foo") @patch("umake.tools.os.path.expanduser") def test_add_env_to_user_not_keep(self, expanderusermock): """Test that adding to user env without keep replace an existing env""" os.environ["FOOO"] = "foo" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"FOOO": {"value": "bar", "keep": False}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=bar\n" in profile_content, profile_content) self.assertTrue("bar" in os.environ["FOOO"], os.environ["FOOO"]) self.assertFalse("foo" in os.environ["FOOO"], os.environ["FOOO"]) self.assertEqual(os.environ["FOOO"], "bar") @patch("umake.tools.os.path.expanduser") def test_add_env_to_user_empty_file(self, expanderusermock): """Test that adding to user env append to an non existing .profile file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") tools.add_env_to_user("one path addition", {"FOOO": {"value": "/tmp/foo"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("export FOOO=/tmp/foo\n" in profile_content, profile_content) self.assertTrue("/tmp/foo" in os.environ["FOOO"], os.environ["FOOO"]) @patch("umake.tools.os.path.expanduser") def test_add_to_user_path_twice(self, expanderusermock): """Test that adding to user env twice doesn't add it twice in the file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("add twice", {"FOOO": {"value": "/tmp/foo"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=/tmp/foo\n" in profile_content, profile_content) tools.add_env_to_user("add twice", {"FOOO": {"value": "/tmp/foo"}}) # ensure, it's only there once profile_content = open(profile_file).read() self.assertEqual(profile_content.count("export FOOO=/tmp/foo"), 1, profile_content) @patch("umake.tools.os.path.expanduser") def test_add_to_user_path_twice_with_new_content(self, expanderusermock): """Test that adding to some env twice for same framework only add the latest""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("add twice", {"FOOO": {"value": "/tmp/foo"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=/tmp/foo\n" in profile_content, profile_content) tools.add_env_to_user("add twice", {"FOOO": {"value": "/tmp/bar"}}) # ensure, it's only there once profile_content = open(profile_file).read() self.assertEqual(profile_content.count("export FOOO=/tmp/bar"), 1, profile_content) @patch("umake.tools.os.path.expanduser") def test_add_to_user_path_twice_other_framework(self, expanderusermock): """Test that adding to user env with another framework add them twice""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("add twice", {"FOOO": {"value": "/tmp/foo"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=/tmp/foo\n" in profile_content, profile_content) tools.add_env_to_user("add twice with other framework", {"BAR": {"value": "/tmp/bar"}}) # ensure, it's only there once profile_content = open(profile_file).read() self.assertTrue("export FOOO=/tmp/foo\n" in profile_content, profile_content) self.assertTrue("export BAR=/tmp/bar\n" in profile_content, profile_content) @patch("umake.tools.os.path.expanduser") def test_add_env_to_user_multiple(self, expanderusermock): """Test that adding to user with multiple env for same framework appending to an existing .profile file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"FOOO": {"value": "bar"}, "BAR": {"value": "foo"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("export FOOO=bar\n" in profile_content, profile_content) self.assertTrue("export BAR=foo\n" in profile_content, profile_content) self.assertEqual(os.environ["FOOO"], "bar") self.assertEqual(os.environ["BAR"], "foo") @patch("umake.tools.os.path.expanduser") def test_add_path_to_user(self, expanderusermock): """Test that adding to user path doesn't export as PATH is already exported""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n") tools.add_env_to_user("one path addition", {"PATH": {"value": "/tmp/bar"}}) expanderusermock.assert_called_with('~') profile_content = open(profile_file).read() self.assertTrue("Foo\nBar\n" in profile_content, profile_content) # we kept previous content self.assertTrue("\nPATH=/tmp/bar:$PATH\n" in profile_content, profile_content) self.assertTrue("/tmp/bar" in os.environ["PATH"], os.environ["PATH"]) @patch("umake.tools.os.path.expanduser") def test_remove_user_env(self, expanderusermock): """Remove an env from a user setup""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n# Ubuntu make installation of framework A" "\nexport FOO=bar\n\nexport BAR=baz") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\nexport BAR=baz") @patch("umake.tools.os.path.expanduser") def test_remove_user_env_end(self, expanderusermock): """Remove an env from a user setup being at the end of profile file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n# Ubuntu make installation of framework A" "\nexport FOO=bar\n\n") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\n") @patch("umake.tools.os.path.expanduser") def test_remove_user_env_not_found(self, expanderusermock): """Remove an env from a user setup with no matching content found""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\nexport BAR=baz") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\nexport BAR=baz") @patch("umake.tools.os.path.expanduser") def test_remove_user_env_no_file(self, expanderusermock): """Remove an env from a user setup with no profile file""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") tools.remove_framework_envs_from_user("framework A") self.assertRaises(FileNotFoundError, open, profile_file) @patch("umake.tools.os.path.expanduser") def test_remove_user_env_multiple_frameworks(self, expanderusermock): """Remove an env from a user setup restraining to the correct framework""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n# Ubuntu make installation of framework B\nexport BAR=bar\n\n" "# Ubuntu make installation of framework A\nexport FOO=bar\n\nexport BAR=baz") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\n# Ubuntu make installation of framework B\nexport BAR=bar\n\n" "export BAR=baz") @patch("umake.tools.os.path.expanduser") def test_remove_user_env_multiple_lines(self, expanderusermock): """Remove an env from a user setup having multiple lines""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n# Ubuntu make installation of framework A" "\nexport FOO=bar\nexport BOO=foo\n\nexport BAR=baz") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\nexport BAR=baz") @patch("umake.tools.os.path.expanduser") def test_remove_user_multiple_same_framework(self, expanderusermock): """Remove an env from a user setup, same framework being repeated multiple times""" expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".profile") open(profile_file, 'w').write("Foo\nBar\n# Ubuntu make installation of framework A\nexport BAR=bar\n\n" "# Ubuntu make installation of framework A\nexport FOO=bar\n\nexport BAR=baz") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\nexport BAR=baz") @patch("umake.tools.os.path.expanduser") def test_remove_user_env_zsh(self, expanderusermock): """Remove an env from a user setup using zsh""" os.environ['SHELL'] = '/bin/zsh' expanderusermock.return_value = self.local_dir profile_file = os.path.join(self.local_dir, ".zprofile") open(profile_file, 'w').write("Foo\nBar\n# Ubuntu make installation of framework A" "\nexport FOO=bar\n\nexport BAR=baz") tools.remove_framework_envs_from_user("framework A") profile_content = open(profile_file).read() self.assertEqual(profile_content, "Foo\nBar\nexport BAR=baz") class TestUserShell(LoggedTestCase): def setUp(self): super().setUp() self.orig_environ = os.environ.copy() os.environ['SHELL'] = '/bin/bash' def tearDown(self): os.environ = self.orig_environ.copy() super().tearDown() def test_return_shell_bash(self): """Default setup should change the bash profile""" self.assertTrue(tools._get_shell_profile_file_path().endswith(".profile")) def test_can_override_zsh_with_SHELL(self): """Can return zsh profile if set""" os.environ['SHELL'] = '/bin/zsh' self.assertTrue(tools._get_shell_profile_file_path().endswith(".zprofile")) def test_return_bash_if_nosense(self): """Return bash if content is garbage""" os.environ['SHELL'] = 'contain_nothing' self.assertTrue(tools._get_shell_profile_file_path().endswith(".profile")) def test_return_bash_if_empty(self): """Return bash if no key""" os.environ.pop('SHELL') self.assertTrue(tools._get_shell_profile_file_path().endswith(".profile")) ubuntu-make-16.11.1ubuntu1/tests/small/test_frameworks_loader.py0000664000000000000000000016717313013560574021746 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests the framework loader""" import argparse from contextlib import suppress import importlib import os import shutil import sys import tempfile from ..data.testframeworks.uninstantiableframework import Uninstantiable, InheritedFromUninstantiable from ..tools import get_data_dir, change_xdg_path, patchelem, LoggedTestCase, INSTALL_DIR import umake from umake import frameworks from umake.frameworks.baseinstaller import BaseInstaller from umake.settings import UMAKE_FRAMEWORKS_ENVIRON_VARIABLE from umake.tools import NoneDict, ConfigHandler from unittest.mock import Mock, patch, call class BaseFrameworkLoader(LoggedTestCase): """Unload and reload the module to ensure we clean all class dict""" @classmethod def setUpClass(cls): super().setUpClass() importlib.reload(frameworks) cls.CategoryHandler = frameworks.BaseCategory def setUp(self): """Ensure we don't have any config file loaded""" super().setUp() change_xdg_path('XDG_CONFIG_HOME', self.config_dir_for_name("foo")) def tearDown(self): change_xdg_path('XDG_CONFIG_HOME', remove=True) # we reset the loaded categories self.CategoryHandler.categories = NoneDict() super().tearDown() def config_dir_for_name(self, name): """Return the config dir for this name""" return os.path.join(get_data_dir(), 'configs', name) def fake_arch_version(self, arch, version): """Help to mock the current arch and version on further calls""" self._saved_current_arch_fn = umake.frameworks.get_current_arch self.get_current_arch_mock = Mock() self.get_current_arch_mock.return_value = arch umake.frameworks.get_current_arch = self.get_current_arch_mock self._saved_current_ubuntu_version_fn = umake.frameworks.get_current_ubuntu_version self.get_current_ubuntu_version_mock = Mock() self.get_current_ubuntu_version_mock.return_value = version umake.frameworks.get_current_ubuntu_version = self.get_current_ubuntu_version_mock def restore_arch_version(self): """Restore initial current arch and version""" umake.frameworks.get_current_arch = self._saved_current_arch_fn umake.frameworks.get_current_ubuntu_version = self._saved_current_ubuntu_version_fn class TestFrameworkLoader(BaseFrameworkLoader): """This will test the dynamic framework loader activity""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() # fake versions and archs self.fake_arch_version("bar", "10.10.10") # load custom framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() self.categoryA = self.CategoryHandler.categories["category-a"] def tearDown(self): self.restore_arch_version() super().tearDown() def test_load_main_category(self): """The main category is loaded""" self.assertEqual(len([1 for category in self.CategoryHandler.categories.values() if category.is_main_category]), 1, str(self.CategoryHandler.categories.values())) def test_get_main_category(self): """main_category property returns main category""" main_category = [category for category in self.CategoryHandler.categories.values() if category.is_main_category][0] self.assertEqual(self.CategoryHandler.main_category, main_category) def test_load_category(self): """There is at least one category (not main) loaded""" self.assertTrue(len([1 for category in self.CategoryHandler.categories.values() if not category.is_main_category]) > 0, str(self.CategoryHandler.categories.values())) def test_get_category_by_prog_name(self): """categories index returns matching category""" category = self.CategoryHandler.categories["category-a"] self.assertEqual(category.name, "Category A") def test_get_framework_by_prog_name(self): """Framework index returns matching framework""" framework = self.categoryA.frameworks["framework-a"] self.assertEqual(framework.name, "Framework A") def test_get_category_not_existing(self): """the call to get category returns None when there is no match""" self.assertIsNone(self.CategoryHandler.categories["foo"]) def test_get_category_prog_name(self): """prog_name for category is what we expect""" self.assertEqual(self.categoryA.prog_name, "category-a") self.assertEqual(self.CategoryHandler.categories["category-b"].prog_name, "category-b") def test_multiple_files_loaded(self): """We load multiple categories in different files""" # main category, + at least 2 other categories self.assertTrue(len(self.CategoryHandler.categories) > 2, str(self.CategoryHandler.categories)) self.assertIsNotNone(self.categoryA) self.assertIsNotNone(self.CategoryHandler.categories["category-b"]) def test_frameworks_loaded(self): """We have frameworks attached to a category""" self.assertTrue(len(self.categoryA.frameworks) > 1, str(self.categoryA.frameworks)) self.assertTrue(self.categoryA.has_frameworks()) def test_framework_not_existing(self): """the call to get a framework returns None when there is no match""" self.assertIsNone(self.categoryA.frameworks["foo"]) def test_frameworks_doesn_t_mix(self): """Frameworks, even with the same name, don't mix between categories""" self.assertNotEqual(self.categoryA.frameworks["framework-a"], self.CategoryHandler.categories["category-b"].frameworks["framework-a"]) def test_has_more_than_one_framework(self): """more than one frameworks in a category is correctly reported""" self.assertFalse(self.categoryA.has_one_framework()) def test_empty_category_loaded(self): """We still load an empty category""" self.assertIsNotNone(self.CategoryHandler.categories["empty-category"]) def test_has_frameworks_on_empty_category(self): """has_frameworks return False on empty category""" self.assertFalse(self.CategoryHandler.categories["empty-category"].has_frameworks()) self.assertFalse(self.CategoryHandler.categories["empty-category"].has_one_framework()) def test_one_framework_category(self): """A category with one framework is reported as so""" self.assertTrue(self.CategoryHandler.categories["one-framework-category"].has_one_framework()) def test_framework_prog_name(self): """prog_name for framework is what we expect""" self.assertEqual(self.categoryA.frameworks["framework-a"].prog_name, "framework-a") self.assertEqual(self.categoryA.frameworks["framework-b"].prog_name, "framework-b") def test_nothing_installed(self): """Category returns that no framework is installed""" self.assertEqual(self.categoryA.is_installed, self.CategoryHandler.NOT_INSTALLED) def test_category_fully_installed(self): """Category returns than all frameworks are installed""" self.assertEqual(self.CategoryHandler.categories["category-b"].is_installed, self.CategoryHandler.FULLY_INSTALLED) def test_category_half_installed(self): """Category returns than half frameworks are installed""" self.assertEqual(self.CategoryHandler.categories["category-c"].is_installed, self.CategoryHandler.PARTIALLY_INSTALLED) def test_frameworks_loaded_in_main_category(self): """Some frameworks are loaded and attached to main category""" self.assertTrue(len(self.CategoryHandler.main_category.frameworks) > 1, str(self.CategoryHandler.main_category.frameworks)) self.assertIsNotNone(self.CategoryHandler.main_category.frameworks["framework-free-a"]) self.assertIsNotNone(self.CategoryHandler.main_category.frameworks["framework-free---b"]) def test_frameworks_report_installed(self): """Frameworks have an is_installed property""" category = self.CategoryHandler.categories["category-c"] self.assertFalse(category.frameworks["framework-a"].is_installed) self.assertTrue(category.frameworks["framework-b"].is_installed) def test_default_framework(self): """Test that a default framework flag is accessible""" framework_default = self.categoryA.frameworks["framework-a"] self.assertEqual(self.categoryA.default_framework, framework_default) def test_default_install_path(self): """Default install path is what we expect, based on category-and framework prog_name""" self.assertEqual(self.categoryA.frameworks["framework-b"].install_path, os.path.expanduser("~/{}/category-a/framework-b".format(INSTALL_DIR))) def test_specified_at_load_install_path(self): """Default install path is overriden by framework specified install path at load time""" self.assertEqual(self.categoryA.frameworks["framework-a"].install_path, os.path.expanduser("~/{}/custom/frameworka".format(INSTALL_DIR))) def test_no_restriction_installable_framework(self): """Framework with an no arch or version restriction is installable""" self.assertTrue(self.categoryA.frameworks["framework-a"].is_installable) def test_right_arch_right_version_framework(self): """Framework with a correct arch and correct version is installable""" self.assertTrue(self.CategoryHandler.categories["category-d"].frameworks["framework-c"].is_installable) def test_unsupported_arch_framework(self): """Framework with an unsupported arch isn't registered""" self.assertIsNone(self.CategoryHandler.categories["category-d"].frameworks["framework-a"]) def test_unsupported_version_framework(self): """Framework with an unsupported arch isn't registered""" self.assertIsNone(self.CategoryHandler.categories["category-d"].frameworks["framework-b"]) def test_child_installable_chained_parent(self): """Framework with an is_installable chained to parent""" self.assertTrue(self.CategoryHandler.categories["category-e"].frameworks["framework-a"].is_installable) def test_child_installable_overridden(self): """Framework with an is_installable override to True from children (with unmatched restrictions)""" self.assertTrue(self.CategoryHandler.categories["category-e"].frameworks["framework-b"].is_installable) def test_child_installable_overridden_false(self): """Framework with an is_installable override to False from children (with no restrictions)""" self.assertIsNone(self.CategoryHandler.categories["category-e"].frameworks["framework-c"]) def test_check_not_installed_wrong_path(self): """Framework isn't installed path doesn't exist""" self.assertFalse(self.CategoryHandler.categories["category-f"].frameworks["framework-a"].is_installed) def test_check_installed_right_path_no_package_req(self): """Framework is installed if right path but no package req.""" self.assertTrue(self.CategoryHandler.categories["category-f"].frameworks["framework-b"].is_installed) def test_check_unmatched_requirements_not_installed(self): """Framework with unmatched requirements are not registered""" self.assertIsNone(self.CategoryHandler.categories["category-f"].frameworks["framework-c"]) def test_no_root_need_if_no_requirements(self): """Framework with not requirements don't need root access""" self.assertFalse(self.categoryA.frameworks["framework-a"].need_root_access) def test_uninstalled_framework_marked_for_removal_only_not_registered(self): """Uninstalled framework marked for removal only isn't not registered (as we can't install it back)""" self.assertIsNone(self.CategoryHandler.categories["category-r"].frameworks["framework-r-uninstalled"]) def test_installed_framework_not_installable_registered(self): """Installed framework not installable are still registered (can be used for removal)""" self.assertIsNotNone(self.CategoryHandler.categories["category-r"] .frameworks["framework-r-installed-not-installable"]) def test_installed_framework_marked_for_removal_only_registered(self): """Installed framework marked for removal only is registered to be able to remove it""" self.assertIsNotNone(self.CategoryHandler.categories["category-r"].frameworks["framework-r-installed"]) def test_installed_framework_marked_for_removal_only_not_installable(self): """Installed framework that are marked for removal only are not installable""" self.assertFalse(self.CategoryHandler.categories["category-r"].frameworks["framework-r-installed"] .is_installable) def test_parse_category_and_framework_run_correct_framework(self): """Parsing category and framework return right category and framework""" args = Mock() args.category = "category-a" args.destdir = None args.framework = "framework-b" args.accept_license = False args.remove = False with patch.object(self.CategoryHandler.categories[args.category].frameworks["framework-b"], "setup")\ as setup_call: self.CategoryHandler.categories[args.category].run_for(args) self.assertTrue(setup_call.called) self.assertEqual(setup_call.call_args, call(install_path=None, auto_accept_license=False)) def test_parse_no_framework_run_default_for_category(self): """Parsing category will run default framework""" args = Mock() args.category = "category-a" args.destdir = None args.framework = None args.accept_license = False args.remove = False with patch.object(self.CategoryHandler.categories[args.category].frameworks["framework-a"], "setup")\ as setup_call: self.CategoryHandler.categories[args.category].run_for(args) self.assertTrue(setup_call.called) self.assertEqual(setup_call.call_args, call(install_path=None, auto_accept_license=False)) def test_parse_category_and_framework_run_correct_remove_framework(self): """Parsing category and framework with --remove run remove on right category and framework""" args = Mock() args.category = "category-a" args.destdir = None args.framework = "framework-b" args.accept_license = False args.remove = True with patch.object(self.CategoryHandler.categories[args.category].frameworks["framework-b"], "remove")\ as remove_call: self.CategoryHandler.categories[args.category].run_for(args) self.assertTrue(remove_call.called) remove_call.assert_called_with() def test_parse_no_framework_run_default_remove_for_category(self): """Parsing category with --remove will run default framework removal action""" args = Mock() args.category = "category-a" args.framework = None args.remove = True args.accept_license = False args.destdir = None with patch.object(self.CategoryHandler.categories[args.category].frameworks["framework-a"], "remove")\ as remove_call: self.CategoryHandler.categories[args.category].run_for(args) self.assertTrue(remove_call.called) remove_call.assert_called_with() def test_parse_no_framework_with_no_default_returns_errors(self): """Parsing a category with no default returns an error when calling run""" args = Mock() args.category = "category-b" args.framework = None args.accept_license = False args.remove = False self.assertRaises(BaseException, self.CategoryHandler.categories[args.category].run_for, args) self.expect_warn_error = True def test_parse_category_and_framework_cannot_run_remove_with_destdir_framework(self): """Parsing category and framework with remove and destdir raises an error""" args = Mock() args.category = "category-a" args.framework = "framework-b" args.remove = True args.accept_license = False self.assertRaises(BaseException, self.CategoryHandler.categories[args.category].run_for, args) self.expect_warn_error = True def test_parse_category_and_framework_cannot_install_not_installable_but_installed_framework(self): """We cannot install frameworks that are not installable but already installed (and so, registered)""" self.expect_warn_error = True args = Mock() args.category = "category-r" args.destdir = None args.framework = "framework-r-installed-not-installable" args.accept_license = False args.remove = False self.assertRaises(BaseException, self.CategoryHandler.categories[args.category].run_for, args) def test_parse_category_and_framework_can_remove_not_installable_but_installed_framework(self): """Parsing category and frameworks with --remove can remove not installable but installed framework""" args = Mock() args.category = "category-r" args.destdir = None args.framework = "framework-r-installed" args.accept_license = False args.remove = True with patch.object(self.CategoryHandler.categories[args.category].frameworks["framework-r-installed"], "remove")\ as remove_call: self.CategoryHandler.categories[args.category].run_for(args) self.assertTrue(remove_call.called) remove_call.assert_called_with() def test_parse_category_and_framework_get_accept_license_arg(self): """Parsing category and framework get the accept license arg""" args = Mock() args.category = "category-a" args.destdir = None args.framework = "framework-b" args.accept_license = True args.remove = False with patch.object(self.CategoryHandler.categories[args.category].frameworks["framework-b"], "setup")\ as setup_call: self.CategoryHandler.categories[args.category].run_for(args) self.assertTrue(setup_call.called) self.assertEqual(setup_call.call_args, call(install_path=None, auto_accept_license=True)) def test_uninstantiable_framework(self): """A uninstantiable framework isn't loaded""" # use the string as we fake the package when loading them self.assertNotIn(str(Uninstantiable).split('.')[-1], [str(type(framework)).split('.')[-1] for framework in self.CategoryHandler.main_category.frameworks.values()]) def test_inherited_from_uninstantiable_framework(self): """We can attach a framework which inherit from an uninstantiable one""" # use the string as we fake the package when loading them self.assertIn(str(InheritedFromUninstantiable).split('.')[-1], [str(type(framework)).split('.')[-1] for framework in self.CategoryHandler.main_category.frameworks.values()]) class TestFrameworkLoaderWithValidConfig(BaseFrameworkLoader): """This will test the dynamic framework loader activity with a valid configuration""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): # load valid configuration super().setUp() change_xdg_path('XDG_CONFIG_HOME', self.config_dir_for_name("valid")) # load custom framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() self.categoryA = self.CategoryHandler.categories["category-a"] def tearDown(self): change_xdg_path('XDG_CONFIG_HOME', remove=True) super().tearDown() def test_config_override_defaults(self): """Configuration override defaults (explicit or implicit). If not present in config, still load default""" # was overridden with at load time self.assertEqual(self.categoryA.frameworks["framework-a"].install_path, "/home/didrocks/quickly/ubuntu-make/adt-eclipse") # was default self.assertEqual(self.categoryA.frameworks["framework-b"].install_path, "/home/didrocks/foo/bar/android-studio") # isn't in the config self.assertEqual(self.CategoryHandler.categories['category-c'].frameworks["framework-a"].install_path, os.path.expanduser("~/{}/category-c/framework-a".format(INSTALL_DIR))) class TestFrameworkLoaderSaveConfig(BaseFrameworkLoader): """This will test the dynamic framework loader activity being able to save some configurations""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() # load custom framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() self.categoryA = self.CategoryHandler.categories["category-a"] self.config_dir = tempfile.mkdtemp() change_xdg_path('XDG_CONFIG_HOME', self.config_dir) def tearDown(self): change_xdg_path('XDG_CONFIG_HOME', remove=True) shutil.rmtree(self.config_dir) super().tearDown() def test_call_mark_in_config_save_config(self): """Calling mark_in_config save path in the configuration""" # load custom framework-directory self.categoryA.frameworks["framework-b"].mark_in_config() self.assertEqual(ConfigHandler().config, {'frameworks': { 'category-a': { 'framework-b': { 'path': os.path.expanduser('~/{}/category-a/framework-b'.format(INSTALL_DIR)) }}}}) def test_call_setup_save_and_then_mark_in_config_tweaked_path(self): """Calling mark_in_config with a custom install path save it in the configuration""" # load custom framework-directory fw = self.categoryA.frameworks["framework-b"] fw.setup() fw.install_path = "/home/foo/bar" self.categoryA.frameworks["framework-b"].mark_in_config() self.assertEqual(ConfigHandler().config, {'frameworks': { 'category-a': { 'framework-b': {'path': '/home/foo/bar'} }}}) def test_call_remove_from_config(self): """Calling remove_from_config remove a framework from the config""" ConfigHandler().config = {'frameworks': { 'category-a': { 'framework-b': {'path': os.path.expanduser('~/{}/category-a/framework-b'.format(INSTALL_DIR))} }}} self.categoryA.frameworks["framework-b"].remove_from_config() self.assertEqual(ConfigHandler().config, {'frameworks': {'category-a': {}}}) def test_call_remove_from_config_keep_other(self): """Calling remove_from_config remove a framework from the config but keep others""" ConfigHandler().config = {'frameworks': { 'category-a': { 'framework-b': {'path': os.path.expanduser('~/{}/category-a/framework-b'.format(INSTALL_DIR))}, 'framework-c': {'path': os.path.expanduser('~/{}/category-a/framework-c'.format(INSTALL_DIR))} }, 'category-b': { 'framework-b': {'path': os.path.expanduser('~/{}/category-a/framework-b'.format(INSTALL_DIR))} }}} self.categoryA.frameworks["framework-b"].remove_from_config() self.assertEqual(ConfigHandler().config, {'frameworks': { 'category-a': { 'framework-c': { 'path': os.path.expanduser('~/{}/category-a/framework-c'.format(INSTALL_DIR)) }}, 'category-b': { 'framework-b': { 'path': os.path.expanduser('~/{}/category-a/framework-b'.format(INSTALL_DIR)) }}}}) class TestFrameworkLoadOnDemandLoader(BaseFrameworkLoader): """This will test the dynamic framework loader activity. This class doesn't load frameworks before the tests does""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() # fake versions and archs self.fake_arch_version("foo", "10.04") def tearDown(self): self.restore_arch_version() super().tearDown() def loadFramework(self, framework_name): """Load framework name""" with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', framework_name): frameworks.load_frameworks() def install_category_parser(self, main_parser, categories=[]): """Install parser for those categories""" categories_parser = main_parser.add_subparsers(dest="category") category_parsers = [] for category in categories: with patch('umake.frameworks.is_completion_mode') as completionmode_mock: completionmode_mock.return_value = False self.loadFramework("testframeworks") category_parsers.append(self.CategoryHandler.categories[category] .install_category_parser(categories_parser)) return category_parsers def test_arch_report_issue_framework(self): """Framework where we can't reach arch and having a restriction isn't installable""" self.get_current_arch_mock.side_effect = BaseException('arch detection failure!') self.loadFramework("testframeworks") # restricted arch framework isn't installable self.assertIsNone(self.CategoryHandler.categories["category-d"].frameworks["framework-a"]) # framework with no arch restriction but others are still installable self.assertTrue(self.CategoryHandler.categories["category-d"].frameworks["framework-b"].is_installable) # framework without any restriction is still installable self.assertTrue(self.CategoryHandler.categories["category-a"].frameworks["framework-a"].is_installable) self.expect_warn_error = True def test_version_report_issue_framework(self): """Framework where we can't reach version and having a restriction isn't installable""" self.get_current_ubuntu_version_mock.side_effect = BaseException('version detection failure!') self.loadFramework("testframeworks") # restricted version framework isn't installable self.assertIsNone(self.CategoryHandler.categories["category-d"].frameworks["framework-b"]) # framework with no version restriction but others are still installable self.assertTrue(self.CategoryHandler.categories["category-d"].frameworks["framework-a"].is_installable) # framework without any restriction is still installable self.assertTrue(self.CategoryHandler.categories["category-a"].frameworks["framework-a"].is_installable) self.expect_warn_error = True def test_check_not_installed_wrong_requirements(self): """Framework isn't installed if path and package requirements aren't met""" with patch('umake.frameworks.RequirementsHandler') as requirement_mock: requirement_mock.return_value.is_bucket_installed.return_value = False self.loadFramework("testframeworks") self.assertFalse(self.CategoryHandler.categories["category-f"].frameworks["framework-c"].is_installed) requirement_mock.return_value.is_bucket_installed.assert_called_with(['foo', 'bar']) # is_bucket_available is called when it's not installed requirement_mock.return_value.is_bucket_available.assert_has_calls([call(['foo', 'bar'])]) def test_check_installed_with_matched_requirements(self): """Framework is installed if path and package requirements are met""" with patch('umake.frameworks.RequirementsHandler') as requirement_mock: requirement_mock.return_value.is_bucket_installed.return_value = True self.loadFramework("testframeworks") self.assertTrue(self.CategoryHandler.categories["category-f"].frameworks["framework-c"].is_installed) requirement_mock.return_value.is_bucket_installed.assert_called_with(['foo', 'bar']) # we don't call is_bucket_available if requirements are met self.assertFalse(call(['foo', 'bar']) in requirement_mock.return_value.is_bucket_available.call_args_list) def test_check_requirements_inherited_from_category(self): """Framework without package requirements are inherited from category""" with patch('umake.frameworks.RequirementsHandler') as requirement_mock: self.loadFramework("testframeworks") self.assertEqual(self.CategoryHandler.categories["category-g"].frameworks["framework-b"] .packages_requirements, ["baz"]) def test_check_requirements_from_category_merge_into_exiting(self): """Framework with package requirements merged them from the associated category""" with patch('umake.frameworks.RequirementsHandler') as requirement_mock: self.loadFramework("testframeworks") self.assertEqual(self.CategoryHandler.categories["category-g"].frameworks["framework-a"] .packages_requirements, ["buz", "biz", "baz"]) def test_root_needed_if_not_matched_requirements(self): """Framework with unmatched requirements need root access""" with patch('umake.frameworks.RequirementsHandler') as requirement_mock: requirement_mock.return_value.is_bucket_installed.return_value = False self.loadFramework("testframeworks") self.assertTrue(self.CategoryHandler.categories["category-f"].frameworks["framework-c"].need_root_access) def test_no_root_needed_if_matched_requirements_even_uninstalled(self): """Framework which are uninstalled but with matched requirements doesn't need root access""" with patch('umake.frameworks.RequirementsHandler') as requirement_mock: requirement_mock.return_value.is_bucket_installed.return_value = True self.loadFramework("testframeworks") # ensure the framework isn't installed, but the bucket being installed, we don't need root access self.assertFalse(self.CategoryHandler.categories["category-f"].frameworks["framework-a"].is_installed) self.assertFalse(self.CategoryHandler.categories["category-f"].frameworks["framework-a"].need_root_access) def test_root_needed_setup_call_root(self): """Framework with root access needed call sudo""" with patch('umake.frameworks.subprocess') as subprocess_mock,\ patch.object(umake.frameworks.os, 'geteuid', return_value=1000) as geteuid,\ patch('umake.frameworks.MainLoop') as mainloop_mock,\ patch('umake.frameworks.RequirementsHandler') as requirement_mock: requirement_mock.return_value.is_bucket_installed.return_value = False self.loadFramework("testframeworks") self.assertTrue(self.CategoryHandler.categories["category-f"].frameworks["framework-c"].need_root_access) self.CategoryHandler.categories["category-f"].frameworks["framework-c"].setup() self.assertEqual(subprocess_mock.call.call_args[0][0][0], "sudo") self.assertTrue(mainloop_mock.return_value.quit.called) def test_no_root_needed_setup_doesnt_call_root(self): """Framework without root access needed don't call sudo""" with patch('umake.frameworks.subprocess') as subprocess_mock,\ patch.object(umake.frameworks.os, 'geteuid', return_value=1000) as geteuid,\ patch.object(umake.frameworks.sys, 'exit', return_value=True) as sys_exit_mock,\ patch('umake.frameworks.RequirementsHandler') as requirement_mock: requirement_mock.return_value.is_bucket_installed.return_value = True self.loadFramework("testframeworks") self.assertFalse(self.CategoryHandler.categories["category-f"].frameworks["framework-c"].need_root_access) self.CategoryHandler.categories["category-f"].frameworks["framework-c"].setup() self.assertFalse(subprocess_mock.call.called) self.assertFalse(sys_exit_mock.called) def test_root_needed_setup_doesnt_call_root(self): """setup doesn't call sudo if we are already root""" with patch('umake.frameworks.subprocess') as subprocess_mock,\ patch.object(umake.frameworks.sys, 'exit', return_value=True) as sys_exit_mock,\ patch.object(umake.frameworks.os, 'geteuid', return_value=0) as geteuid,\ patch('umake.frameworks.RequirementsHandler') as requirement_mock,\ patch('umake.frameworks.switch_to_current_user') as switch_to_current_use_mock: requirement_mock.return_value.is_bucket_installed.return_value = False self.loadFramework("testframeworks") self.assertTrue(self.CategoryHandler.categories["category-f"].frameworks["framework-c"].need_root_access) self.CategoryHandler.categories["category-f"].frameworks["framework-c"].setup() self.assertFalse(subprocess_mock.call.called) self.assertFalse(sys_exit_mock.called) geteuid.assert_called_once_with() switch_to_current_use_mock.assert_called_once_with() def test_completion_mode_dont_use_expensive_calls(self): """Completion mode bypass expensive calls and so, register all frameworks but those marked as only for removal (so read config)""" with patch('umake.frameworks.ConfigHandler') as config_handler_mock,\ patch('umake.frameworks.RequirementsHandler') as requirementhandler_mock,\ patch('umake.frameworks.is_completion_mode') as completionmode_mock: completionmode_mock.return_value = True self.loadFramework("testframeworks") self.assertTrue(completionmode_mock.called) self.assertFalse(requirementhandler_mock.return_value.is_bucket_installed.called) # test that a non installed framework is registered self.assertIsNotNone(self.CategoryHandler.categories["category-e"].frameworks["framework-c"]) def test_use_expensive_calls_when_not_in_completion_mode(self): """Non completion mode have expensive calls and don't register all frameworks""" with patch('umake.frameworks.ConfigHandler') as config_handler_mock,\ patch('umake.frameworks.RequirementsHandler') as requirementhandler_mock,\ patch('umake.frameworks.is_completion_mode') as completionmode_mock: completionmode_mock.return_value = False self.loadFramework("testframeworks") self.assertTrue(completionmode_mock.called) self.assertTrue(len(config_handler_mock.return_value.config.mock_calls) > 0, str(config_handler_mock.return_value.config.mock_calls)) self.assertTrue(requirementhandler_mock.return_value.is_bucket_installed.called) # test that a non installed framework is registered self.assertIsNone(self.CategoryHandler.categories["category-e"].frameworks["framework-c"]) def test_install_category_and_framework_parsers(self): """Install category and framework parsers contains works""" main_parser = argparse.ArgumentParser() categories_parser = main_parser.add_subparsers() with patch('umake.frameworks.is_completion_mode') as completionmode_mock: completionmode_mock.return_value = False self.loadFramework("testframeworks") category_parser = self.CategoryHandler.categories['category-a'].install_category_parser(categories_parser) self.assertTrue('category-a' in categories_parser.choices) self.assertTrue('framework-a' in category_parser.choices) self.assertTrue('framework-b' in category_parser.choices) def test_parse_category_and_framework(self): """Parsing category and framework return right category and framework""" main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ['category-a']) args = main_parser.parse_args(["category-a", "framework-a"]) self.assertEqual(args.category, "category-a") self.assertEqual(args.framework, "framework-a") self.assertEqual(args.destdir, None) def test_parse_framework(self): """Parsing framework get default parser framework options""" main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ['category-a']) args = main_parser.parse_args(["category-a", "framework-a"]) self.assertEqual(args.category, "category-a") self.assertEqual(args.framework, "framework-a") self.assertEqual(args.destdir, None) self.assertFalse(args.remove) with self.assertRaises(AttributeError): args.accept_license def test_parse_framework_with_optional_accept_license(self): """Parsing framework with optional auto accept license argument""" main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ['category-a']) args = main_parser.parse_args(["category-a", "framework-b", "--accept-license"]) self.assertEqual(args.category, "category-a") self.assertEqual(args.framework, "framework-b") self.assertEqual(args.destdir, None) self.assertFalse(args.remove) self.assertTrue(args.accept_license) def test_parse_invalid_categories_raise_exit_error(self): """Invalid categories parse requests exit""" def error_without_message(x): raise SystemExit() main_parser = argparse.ArgumentParser() main_parser.print_usage = lambda x: "" main_parser.error = error_without_message self.install_category_parser(main_parser, []) self.assertRaises(SystemExit, main_parser.parse_args, ["category-a", "framework-a"]) def test_parse_invalid_frameworks_return_error(self): """Invalid framework parse requests exit""" def error_without_message(x): raise SystemExit() main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ["category-a"]) category_parser = main_parser._actions[1].choices["category-a"] category_parser.print_usage = lambda x: "" category_parser.error = error_without_message self.assertRaises(SystemExit, main_parser.parse_args, ["category-a", "framework-aa"]) def test_parse_no_category_return_empty_namespace(self): """No category or framework returns an empty namespace""" main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ['category-a']) self.assertEqual(main_parser.parse_args([]), argparse.Namespace(category=None)) def test_install_category_with_no_framework(self): """Install category with no framework returns None""" main_parser = argparse.ArgumentParser() self.assertEqual(self.install_category_parser(main_parser, ['empty-category']), [None]) def test_install_main_category(self): """Main category install directly at root of the parser""" main_parser = argparse.ArgumentParser() main_cat_parser = self.install_category_parser(main_parser, ['main'])[0] self.assertTrue('framework-free---b' in main_cat_parser.choices) self.assertTrue('framework-free-a' in main_cat_parser.choices) self.assertFalse('framework-a' in main_cat_parser.choices) def test_parse_main_category(self): """Main category elements can be directly accessed""" main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ['main']) args = main_parser.parse_args(["framework-free-a"]) self.assertEqual(args.category, "framework-free-a") self.assertEqual(args.destdir, None) self.assertFalse("framework" in args) def test_run_framework_in_main_category(self): """Frameworks command from main category can be run as usual""" main_parser = argparse.ArgumentParser() self.install_category_parser(main_parser, ['main']) args = main_parser.parse_args(["framework-free-a"]) with patch.object(self.CategoryHandler.main_category.frameworks["framework-free-a"], "setup") as setup_call: self.CategoryHandler.main_category.frameworks["framework-free-a"].run_for(args) self.assertTrue(setup_call.called) class TestEmptyFrameworkLoader(BaseFrameworkLoader): """This will test the dynamic framework loader activity with an empty set of frameworks""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworksdoesntexist') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() # load custom unexisting framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworksdoesntexist"): frameworks.load_frameworks() def test_invalid_framework(self): """There is one main category, but nothing else""" main_category = [category for category in self.CategoryHandler.categories.values() if category.is_main_category][0] self.assertEqual(self.CategoryHandler.main_category, main_category) self.assertEqual(len(self.CategoryHandler.categories), 1, str(self.CategoryHandler.categories)) class TestDuplicatedFrameworkLoader(BaseFrameworkLoader): """This will test the dynamic framework loader activity with some duplicated categories and frameworks""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'duplicatedframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "duplicatedframeworks"): frameworks.load_frameworks() self.categoryA = self.CategoryHandler.categories["category-a"] self.expect_warn_error = True # as we load multiple duplicate categories and frameworks def test_duplicated_categories(self): """We only load one category when a second with same name is met""" # main + categoryA self.assertEqual(len(self.CategoryHandler.categories), 2, str(self.CategoryHandler.categories)) self.assertEqual(self.CategoryHandler.categories["category-a"].name, "Category A") def test_duplicated_frameworks(self): """We only load one framework when a second with the same name is met""" self.assertEqual(len(self.categoryA.frameworks), 1, str(self.categoryA.frameworks)) def test_main_category_empty(self): """The main category (unused here) is empty by default""" self.assertEqual(len(self.CategoryHandler.main_category.frameworks), 0, str(self.CategoryHandler.main_category.frameworks)) class TestMultipleDefaultFrameworkLoader(BaseFrameworkLoader): """This will test if we try to load multiple default frameworsk in loader""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'multipledefaultsframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "multipledefaultsframeworks"): frameworks.load_frameworks() self.categoryA = self.CategoryHandler.categories["category-a"] self.expect_warn_error = True # as we load multiple default frameworks in a category def test_multiple_defaults(self): """Setting multiple defaults frameworks to a category should void any default""" self.assertIsNone(self.categoryA.default_framework) self.assertEqual(len(self.categoryA.frameworks), 2, str(self.categoryA.frameworks)) # ensure they are still loaded def test_one_default_in_main_category(self): """Reject default framework for main category""" self.assertIsNone(self.CategoryHandler.main_category.default_framework) self.assertEqual(len(self.CategoryHandler.main_category.frameworks), 1, str(self.CategoryHandler.main_category.frameworks)) # ensure it's still loaded class TestNotLoadedFrameworkLoader(BaseFrameworkLoader): def setUp(self): super().setUp() self.CategoryHandler = frameworks.BaseCategory def test_get_no_main_category(self): """main_category returns None when there is no main category""" self.assertIsNone(self.CategoryHandler.main_category) def test_get_with_no_category(self): """categories is empty when there is no category loaded""" self.assertEqual(len(self.CategoryHandler.categories), 0, str(self.CategoryHandler.categories)) class TestAbstractFrameworkLoader(BaseFrameworkLoader): """Test the loader skips abstract frameworks.""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'abstractframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() # load custom unexisting framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "abstractframeworks"): frameworks.load_frameworks() self.categoryA = self.CategoryHandler.categories["category-a"] def test_load(self): """Previous loading should have been successful""" self.assertFalse(self.categoryA.has_frameworks()) self.expect_warn_error = False # Should be silent. class TestInvalidFrameworksLoader(BaseFrameworkLoader): """Test the loader handles badly formatted frameworks.""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'invalidframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def test_invalid_framework_loading(self): """Frameworks that don't have a Framework type aren't loaded""" with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "invalidframeworks"): frameworks.load_frameworks() self.assertEqual(len(self.CategoryHandler.categories["category-a"].frameworks), 0, self.CategoryHandler.categories["category-a"].frameworks) class TestFrameworkLoaderCustom(BaseFrameworkLoader): """This will test the dynamic framework loader activity with custom path""" @classmethod def setUpClass(cls): super().setUpClass() sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworks') @classmethod def tearDownClass(cls): sys.path.remove(get_data_dir()) super().tearDownClass() def setUp(self): super().setUp() # fake versions and archs self.fake_arch_version("bar", "10.10.10") self.dirs_to_remove = [] def tearDown(self): self.restore_arch_version() with suppress(KeyError): os.environ.pop(UMAKE_FRAMEWORKS_ENVIRON_VARIABLE) for path in self.dirs_to_remove: sys.path.remove(path) with suppress(FileNotFoundError): shutil.rmtree(path) with suppress(ValueError): sys.path.remove(path) super().tearDown() @patch("umake.frameworks.get_user_frameworks_path") def test_load_additional_frameworks_in_home_dir(self, get_user_frameworks_path): """Ensure we load additional frameworks from home directory""" temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "overlayframeworks.py"), temp_path) get_user_frameworks_path.return_value = temp_path # load home framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # ensure that the overlay is loaded self.assertEqual(self.CategoryHandler.categories["category-a-overlay"].name, "Category A overlay") # ensure that the other frameworks are still loaded self.assertEqual(self.CategoryHandler.categories["category-a"].name, "Category A") def test_load_additional_frameworks_with_env_var(self): """Ensure we load additional frameworks set in an environment variable""" temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) os.environ[UMAKE_FRAMEWORKS_ENVIRON_VARIABLE] = temp_path shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "overlayframeworks.py"), temp_path) # load env framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # ensure that the overlay is loaded self.assertEqual(self.CategoryHandler.categories["category-a-overlay"].name, "Category A overlay") # ensure that the other frameworks are still loaded self.assertEqual(self.CategoryHandler.categories["category-a"].name, "Category A") @patch("umake.frameworks.get_user_frameworks_path") def test_load_additional_frameworks_with_two_categories(self, get_user_frameworks_path): """Ensure we load additional frameworks in a path with two categories""" temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "overlayframeworks.py"), temp_path) shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "withcategory2.py"), temp_path) get_user_frameworks_path.return_value = temp_path # load home framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # ensure that both overlay are loaded self.assertEqual(self.CategoryHandler.categories["category-a-overlay"].name, "Category A overlay") self.assertEqual(self.CategoryHandler.categories["category-a2-overlay"].name, "Category A2 overlay") # ensure that the other frameworks are still loaded self.assertEqual(self.CategoryHandler.categories["category-a"].name, "Category A") @patch("umake.frameworks.get_user_frameworks_path") def test_load_additional_frameworks_with_same_filename(self, get_user_frameworks_path): """Ensure we load additional frameworks in a path with same filename""" temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "withcategory.py"), temp_path) get_user_frameworks_path.return_value = temp_path # load home framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # ensure that the duplicated filename (but not category) is loaded self.assertEqual(self.CategoryHandler.categories["category-a-overlay"].name, "Category A overlay") # ensure that the other frameworks with the same name is still loaded self.assertEqual(self.CategoryHandler.categories["category-a"].name, "Category A") @patch("umake.frameworks.get_user_frameworks_path") def test_load_additional_frameworks_with_duphome_before_system(self, get_user_frameworks_path): """Ensure we load additional frameworks from home before system if they have the same names""" temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "duplicatedcategory.py"), temp_path) get_user_frameworks_path.return_value = temp_path # load home framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # ensure that the overlay one is loaded categoryA = self.CategoryHandler.categories["category-a"] self.assertEqual(categoryA.name, "Category A") self.assertEqual(categoryA.frameworks["framework-a-from-overlay"].name, "Framework A from overlay") # ensure that the other frameworks are still loaded self.assertEqual(self.CategoryHandler.categories["category-b"].name, "Category/B") self.expect_warn_error = True # expect warning due to duplication @patch("umake.frameworks.get_user_frameworks_path") def test_load_additional_frameworks_with_dup_progname_env_before_home_before_system(self, get_user_frameworks_path): """Ensure we load additional frameworks from env before home and system if they have the same names""" # env var temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) os.environ[UMAKE_FRAMEWORKS_ENVIRON_VARIABLE] = temp_path shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "duplicatedcategory2.py"), temp_path) # home dir temp_path = tempfile.mkdtemp() self.dirs_to_remove.append(temp_path) shutil.copy(os.path.join(get_data_dir(), "overlayframeworks", "duplicatedcategory.py"), temp_path) get_user_frameworks_path.return_value = temp_path # load env and home framework-directory with patchelem(umake.frameworks, '__file__', os.path.join(self.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # ensure that the env overlay one is loaded categoryA = self.CategoryHandler.categories["category-a"] self.assertEqual(categoryA.name, "Category A") self.assertEqual(categoryA.frameworks["framework-a-from-overlay-2"].name, "Framework A from overlay 2") # ensure that the other frameworks are still loaded self.assertEqual(self.CategoryHandler.categories["category-b"].name, "Category/B") self.expect_warn_error = True # expect warning due to duplication class TestProductionFrameworkLoader(BaseFrameworkLoader): """Load production framework-and ensure there is no warning and no error""" def test_load_scala(self): """Can load production frameworks""" frameworks.load_frameworks() self.assertTrue(len(self.CategoryHandler.categories) > 0, str(self.CategoryHandler.categories)) self.assertIsNotNone(self.CategoryHandler.main_category) self.assertEqual(len(self.CategoryHandler.categories["scala"].frameworks), 1, str(self.CategoryHandler.categories["scala"].frameworks)) def test_ignored_frameworks(self): """Ignored frameworks aren't loaded""" frameworks.load_frameworks() self.assertNotIn(BaseInstaller, frameworks.BaseCategory.main_category.frameworks.values()) class TestCustomFrameworkCantLoad(BaseFrameworkLoader): """Get custom unloadable automatically frameworks to test custom corner cases""" class _CustomFramework(umake.frameworks.BaseFramework): def __init__(self): super().__init__(name="Custom", description="Custom uninstallable framework", category=umake.frameworks.MainCategory()) def setup(self): super().setup() def remove(self): super().remove() @property def is_installable(self): return False def test_call_setup_on_uninstallable_framework(self): """Calling setup on uninstallable framework return to main UI""" fw = self._CustomFramework() with patch("umake.frameworks.UI") as UIMock: fw.setup() self.assertTrue(UIMock.return_main_screen.called) self.expect_warn_error = True ubuntu-make-16.11.1ubuntu1/tests/small/test_decompressor.py0000664000000000000000000003565313013560574020742 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the decompressor module""" import os from time import time from unittest.mock import Mock import shutil import stat import tempfile from ..tools import get_data_dir, LoggedTestCase from umake.decompressor import Decompressor class TestDecompressor(LoggedTestCase): """This will test the decompressor class""" @classmethod def setUpClass(cls): super().setUpClass() cls.compressfiles_dir_orig = os.path.join(get_data_dir(), "compress-files") def setUp(self): super().setUp() self.on_done = Mock() self.tempdir = tempfile.mkdtemp() self.compressfiles_dir = os.path.join(self.tempdir, "source-files") shutil.copytree(self.compressfiles_dir_orig, self.compressfiles_dir) def tearDown(self): shutil.rmtree(self.tempdir) super().tearDown() def wait_for_callback(self, mock_function_to_be_called, timeout=10): """wait for the callback to be called until a timeout. Add temp files to the clean file list afterwards""" timeout_time = time() + 5 while not mock_function_to_be_called.called: if time() > timeout_time: raise(BaseException("Function not called within {} seconds".format(timeout))) def test_decompress(self): """We decompress a valid .tgz file successfully""" filepath = os.path.join(self.compressfiles_dir, "valid.tgz") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content', 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'subdir', 'otherfile'))) self.assertEqual(self.on_done.call_count, 1, "Global done callback is only called once") def test_decompress_move_dir_content(self): """We decompress a valid file decompressing one subdir content (other files in root are kept in place)""" filepath = os.path.join(self.compressfiles_dir, "valid.tgz") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='server-content')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(self.tempdir)) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'subdir', 'otherfile'))) def test_decompress_invalid_file(self): """We return an error if the compressed file is invalid""" self.expect_warn_error = True filepath = os.path.join(self.compressfiles_dir, "invalid.tgz") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNotNone(results[fd].error) self.assertEqual(self.on_done.call_count, 1, "Global done callback is only called once") def test_decompress_content_glob(self): """We decompress a valid file decompressing one subdir content with a glob schema""" filepath = os.path.join(self.compressfiles_dir, "valid.tgz") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='server-*')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(self.tempdir)) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'subdir', 'otherfile'))) def test_decompress_zip(self): """We decompress a valid zip file successfully""" filepath = os.path.join(self.compressfiles_dir, "valid.zip") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'simplefile'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'executablefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content', 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'subdir', 'otherfile'))) def test_decompress_zip_good_permission(self): """We decompress a valid zip file successfully, retaining the right permissions""" filepath = os.path.join(self.compressfiles_dir, "valid.zip") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content'))) simplefile = os.path.join(self.tempdir, 'server-content', 'simplefile') self.assertTrue(os.path.isfile(simplefile)) execfile = os.path.join(self.tempdir, 'server-content', 'executablefile') self.assertTrue(os.path.isfile(execfile)) self.assertEqual(oct(stat.S_IMODE(os.lstat(simplefile).st_mode)), '0o664') self.assertEqual(oct(stat.S_IMODE(os.lstat(execfile).st_mode)), '0o775') def test_decompress_exec(self): """We decompress a valid executable file successfully""" filepath = os.path.join(self.compressfiles_dir, "simple.bin") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'android-ndk-foo'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'android-ndk-foo', 'ndk-which'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'android-ndk-foo', 'ndk-build'))) def test_decompress_file_with_archive(self): """We decompress a .sh file containing an archive successfully""" filepath = os.path.join(self.compressfiles_dir, "script_with_archive.sh") with open(filepath, 'rb') as fd: for line in fd: if line.startswith(b"== ARCHIVE TAG =="): break Decompressor({fd: Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content', 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'subdir', 'otherfile'))) def test_decompress_wrong_dir_content(self): """We decompress a valid file, but the selected subdir isn't valid""" self.expect_warn_error = True filepath = os.path.join(self.compressfiles_dir, "valid.tgz") Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='doesnt-exists')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNotNone(results[fd].error) def test_decompress_content_keep_existing_files(self): """We decompress a valid file in a directory which already have some content. This one is left.""" filepath = os.path.join(self.compressfiles_dir, "valid.tgz") open(os.path.join(self.tempdir, "foo"), 'w').write('') Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(self.tempdir)) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content', 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'subdir', 'otherfile'))) # the original file is there here self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'foo'))) def test_decompress_move_dir_content_keep_existing_files(self): """We decompress a valid file changing dir in a directory which already have some content. This one is left.""" filepath = os.path.join(self.compressfiles_dir, "valid.tgz") open(os.path.join(self.tempdir, "foo"), 'w').write('') Decompressor({open(filepath, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='server-content')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 1, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(self.tempdir)) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'subdir', 'otherfile'))) # the original file is there here self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'foo'))) def test_decompress_multiple(self): """We decompress multiple valid .tgz file successfully""" filepath1 = os.path.join(self.compressfiles_dir, "valid.tgz") filepath2 = os.path.join(self.compressfiles_dir, "valid2.tgz") Decompressor({open(filepath1, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir=''), open(filepath2, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 2, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content', 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content', 'subdir', 'otherfile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content2'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content2', 'simplefile2'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'server-content2', 'subdir2'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'server-content2', 'subdir2', 'otherfile'))) self.assertEqual(self.on_done.call_count, 1, "Global done callback is only called once") def test_decompress_multiple_with_dir(self): """We decompress multiple valid .tgz file successfully with different dir to extract""" filepath1 = os.path.join(self.compressfiles_dir, "valid.tgz") filepath2 = os.path.join(self.compressfiles_dir, "valid2.tgz") Decompressor({open(filepath1, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='server-content'), open(filepath2, 'rb'): Decompressor.DecompressOrder(dest=self.tempdir, dir='server-content2')}, self.on_done) self.wait_for_callback(self.on_done) results = self.on_done.call_args[0][0] self.assertEqual(len(results), 2, str(results)) for fd in results: self.assertIsNone(results[fd].error) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'simplefile'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'subdir'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'subdir', 'otherfile'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'simplefile2'))) self.assertTrue(os.path.isdir(os.path.join(self.tempdir, 'subdir2'))) self.assertTrue(os.path.isfile(os.path.join(self.tempdir, 'subdir2', 'otherfile'))) self.assertEqual(self.on_done.call_count, 1, "Global done callback is only called once") ubuntu-make-16.11.1ubuntu1/tests/small/test_settings.py0000664000000000000000000000712313013560574020064 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2015 Canonical # # Authors: # Didier Roche # # 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; version 3. # # This program is distributed in he 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests the umake settings handler""" import os import shutil import tempfile from ..tools import get_data_dir, LoggedTestCase from unittest.mock import patch from umake import settings class TestVersionHandler(LoggedTestCase): """This will test the version handler""" def setUp(self): super().setUp() self.from_dev_opt = settings.from_dev self.version_dir = tempfile.mkdtemp() self.initial_env = os.environ.copy() self.initial_os_path_join = os.path.join os.environ["PATH"] = "{}:{}".format(os.path.join(get_data_dir(), "mocks"), os.getenv("PATH")) self.version_file_path = os.path.join(self.version_dir, "version") open(self.version_file_path, "w").write("42.02") def tearDown(self): # remove caching shutil.rmtree(self.version_dir) settings.from_dev = self.from_dev_opt # restore original environment. Do not use the dict copy which erases the object and doesn't have the magical # _Environ which setenv() for subprocess os.environ.clear() os.environ.update(self.initial_env) os.path.join = self.initial_os_path_join super().tearDown() def return_fake_version_path(self, *args): '''Only return fake version path if the request was for that one''' if args[-1] == "version": return self.version_file_path return self.initial_os_path_join(*args) @patch("os.path.join") def test_version_release(self, path_join_result): """Ensure we are returning the right version for a release""" path_join_result.side_effect = self.return_fake_version_path os.environ.clear() os.environ.update(self.initial_env) self.assertEquals(settings.get_version(), "42.02") @patch("os.path.join") def test_version_git(self, path_join_result): """Ensure we are returning the right version for a git repo""" settings.from_dev = True path_join_result.side_effect = self.return_fake_version_path self.assertEquals(settings.get_version(), "42.03-25-g1fd9507") @patch("os.path.join") def test_version_git_fail(self, path_join_result): """Ensure we are returning last known version + unknown if git fails""" settings.from_dev = True path_join_result.side_effect = self.return_fake_version_path os.environ["PATH"] = "{}:{}".format(os.path.join(get_data_dir(), "mocks", "fails"), os.getenv("PATH")) self.assertEquals(settings.get_version(), "42.02+unknown") @patch("os.path.join") def test_version_git_not_installed(self, path_join_result): """Ensure we are returning last known version + unknown if git isn't installed""" settings.from_dev = True path_join_result.side_effect = self.return_fake_version_path os.environ["PATH"] = "" self.assertEquals(settings.get_version(), "42.02+unknown") ubuntu-make-16.11.1ubuntu1/tests/small/test_cli.py0000664000000000000000000002736713013560574017007 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the cli module""" import importlib from ..tools import LoggedTestCase from umake.ui.cli import mangle_args_for_default_framework import os import sys from ..tools import get_data_dir, change_xdg_path, patchelem import umake from umake import frameworks class TestCLIFromFrameworks(LoggedTestCase): """This will test the CLI module with loaded Frameworks""" @classmethod def setUpClass(cls): super().setUpClass() importlib.reload(umake.frameworks) change_xdg_path('XDG_CONFIG_HOME', os.path.join(get_data_dir(), 'configs', "foo")) sys.path.append(get_data_dir()) cls.testframeworks_dir = os.path.join(get_data_dir(), 'testframeworks') with patchelem(umake.frameworks, '__file__', os.path.join(cls.testframeworks_dir, '__init__.py')),\ patchelem(umake.frameworks, '__package__', "testframeworks"): frameworks.load_frameworks() # patch the BaseCategory dictionary from the umake.ui.cli one umake.ui.cli.BaseCategory = frameworks.BaseCategory @classmethod def tearDownClass(cls): change_xdg_path('XDG_CONFIG_HOME', remove=True) sys.path.remove(get_data_dir()) super().tearDownClass() def test_mangle_args_none(self): """No option goes are preserved""" self.assertEqual(mangle_args_for_default_framework([]), []) def test_mangle_args_options_only(self): """Options only goes are preserved""" self.assertEqual(mangle_args_for_default_framework(["--foo", "-b"]), ["--foo", "-b"]) def test_mangle_args_unknown_category(self): """Unknown category are preserved""" self.assertEqual(mangle_args_for_default_framework(["barframework", "-b"]), ["barframework", "-b"]) def test_mangle_args_for_framework(self): """Well formatted framework command are preserved""" self.assertEqual(mangle_args_for_default_framework(["category-a", "framework-a"]), ["category-a", "framework-a"]) def test_mangle_args_for_framework_none_default(self): """Well formatted none default framework command are preserved""" self.assertEqual(mangle_args_for_default_framework(["category-a", "framework-b"]), ["category-a", "framework-b"]) def test_mangle_args_for_framework_with_framework_options(self): """Well formatted framework command with framework options are preserved""" self.assertEqual(mangle_args_for_default_framework(["category-a", "framework-a", "--bar", "install_path", "--foo"]), ["category-a", "framework-a", "--bar", "install_path", "--foo"]) def test_mangle_args_for_framework_global_options(self): """Well formatted framework with global options are preserved""" self.assertEqual(mangle_args_for_default_framework(["category-a", "framework-a"]), ["category-a", "framework-a"]) def test_mangle_args_default_framework(self): """Choose default framework for the category""" self.assertEqual(mangle_args_for_default_framework(["category-a"]), ["category-a", "framework-a"]) def test_mangle_args_without_framework_with_framework_options(self): """Don't choose any framework for a category with default framework and framework options""" self.assertEqual(mangle_args_for_default_framework(["category-a", "install_path", "--foo"]), ["category-a", "install_path", "--foo"]) def test_mangle_args_for_framework_with_global_options(self): """Global options are preserved""" self.assertEqual(mangle_args_for_default_framework(["-v", "--debug", "category-a", "framework-a"]), ["-v", "--debug", "category-a", "framework-a"]) def test_mangle_args_for_framework_with_global_and_framework_options(self): """Global options and framework options are preserved""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a", "framework-a", "--bar", "install", "--foo"]), ["-v", "category-a", "framework-a", "--bar", "install", "--foo"]) def test_mangle_args_for_default_framework_with_global_options(self): """Global options are preserved, completing with default framework""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a"]), ["-v", "category-a", "framework-a"]) def test_mangle_args_for_default_framework_with_simple_options(self): """Global and framework simple options are preserved, completing with default framework with simple options""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a", "--foo", "--bar"]), ["-v", "category-a", "framework-a", "--foo", "--bar"]) def test_mangle_args_with_global_framework_extended_options(self): """Global options and framework extended options are preserved, NOT completing with default framework""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a", "--bar", "install_path", "--foo"]), ["-v", "category-a", "--bar", "install_path", "--foo"]) def test_mangle_args_with_global_framework_options_after_install(self): """Global and extended framework options are preserved after install_path, NOT completing with dft framework""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a", "install_path", "--foo"]), ["-v", "category-a", "install_path", "--foo"]) def test_mangle_args_for_default_framework_after_install_with_sep(self): """Add the default framework if the install path has a sep""" self.assertEqual(mangle_args_for_default_framework(["category-a", "install/path"]), ["category-a", "framework-a", "install/path"]) def test_mangle_args_with_global_framework_options_after_install_with_sep(self): """Global and ext framework options are preserved after install_path with sep, completing with dft framework""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a", "install/path", "--foo"]), ["-v", "category-a", "framework-a", "install/path", "--foo"]) def test_mangle_args_with_global_framework_options_between_install_with_sep(self): """Global and ext framework options are preserved before install_path with sep, completing with dft framework""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-a", "--bar", "install/path", "--foo"]), ["-v", "category-a", "framework-a", "--bar", "install/path", "--foo"]) def test_mangle_args_for_framework_in_main_category(self): """framework in main category is preserved""" self.assertEqual(mangle_args_for_default_framework(["framework-free-a"]), ["framework-free-a"]) def test_mangle_args_for_framework_in_main_category_with_framework_options(self): """framework in main category with framework simple options are preserved""" self.assertEqual(mangle_args_for_default_framework(["framework-free-a", "--foo"]), ["framework-free-a", "--foo"]) def test_mangle_args_for_framework_in_main_category_with_framework_extended_options(self): """framework in main category with framework extended options are preserved""" self.assertEqual(mangle_args_for_default_framework(["framework-free-a", "--foo", "install_path"]), ["framework-free-a", "--foo", "install_path"]) def test_mangle_args_for_framework_in_main_category_with_global_and_framework_extended_options(self): """framework in main category with framework global and extended options are preserved""" self.assertEqual(mangle_args_for_default_framework(["-v", "framework-free-a", "--foo", "install_path"]), ["-v", "framework-free-a", "--foo", "install_path"]) def test_mangle_args_for_framework_in_main_category_with_global_and_framework_extended_options_and_path(self): """framework in main category with framework global and extended options are preserved and path""" self.assertEqual(mangle_args_for_default_framework(["-v", "framework-free-a", "--foo", "install/path"]), ["-v", "framework-free-a", "--foo", "install/path"]) def test_mangle_args_for_category_without_default_framework(self): """No framework in a category without default are preserved""" self.assertEqual(mangle_args_for_default_framework(["category-f"]), ["category-f"]) def test_mangle_args_for_category_without_default_framework_with_extended_options(self): """No framework in a category with ext. option without default are preserved""" self.assertEqual(mangle_args_for_default_framework(["category-f", "--foo", "install_path"]), ["category-f", "--foo", "install_path"]) def test_mangle_args_for_category_without_default_framework_with_install_path(self): """No framework in a category without default are preserved with install path""" self.assertEqual(mangle_args_for_default_framework(["category-f", "--foo", "install/path"]), ["category-f", "--foo", "install/path"]) def test_mangle_args_for_category_without_default_framework_with_global_and_extended_options(self): """No framework in a category without default are preserved with global and ext options""" self.assertEqual(mangle_args_for_default_framework(["-v", "category-f", "--foo", "install_path"]), ["-v", "category-f", "--foo", "install_path"]) def test_mangle_args_for_category_with_remove_global_options(self): """We mangle the remove option if global (before the category name) to append it to the framework option""" self.assertEqual(mangle_args_for_default_framework(["--remove", "category-a", "framework-a"]), ["category-a", "framework-a", "--remove"]) def test_mangle_args_for_category_with_remove_framework_options_middle(self): """We mangle the remove option if framework (between category and framework)""" self.assertEqual(mangle_args_for_default_framework(["category-a", "--remove", "framework-a"]), ["category-a", "framework-a", "--remove"]) def test_mangle_args_for_category_with_remove_framework_options(self): """We don't change the remove option if after framework""" self.assertEqual(mangle_args_for_default_framework(["category-a", "framework-a", "--remove", "--bar"]), ["category-a", "framework-a", "--remove", "--bar"]) def test_mangle_args_for_category_with_short_remove_global_options(self): """We mangle the -r remove option if global (before the category name) to append it to the framework option""" self.assertEqual(mangle_args_for_default_framework(["-r", "category-a", "framework-a"]), ["category-a", "framework-a", "-r"]) ubuntu-make-16.11.1ubuntu1/tests/small/test_requirements_handler.py0000664000000000000000000006770613013560574022461 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the download center module using a local server""" import os import shutil import subprocess from time import time from unittest.mock import Mock, call, patch import umake from . import DpkgAptSetup from umake.network.requirements_handler import RequirementsHandler from umake import tools class TestRequirementsHandler(DpkgAptSetup): """This will test the download center by sending one or more download requests""" @classmethod def setUpClass(cls): super().setUpClass() cls.handler = RequirementsHandler() def count_number_progress_call(self, call_args_list, tag): """Count the number of tag in progress call and return it""" count = 0 for call in call_args_list: if call[0][0]['step'] == tag: count += 1 return count def wait_for_callback(self, mock_function_to_be_called, timeout=10): """wait for the callback to be called until a timeout. Add temp files to the clean file list afterwards""" timeout_time = time() + timeout while not mock_function_to_be_called.called: if time() > timeout_time: raise(BaseException("Function not called within {} seconds".format(timeout))) def test_singleton(self): """Ensure we are delivering a singleton for RequirementsHandler""" other = RequirementsHandler() self.assertEqual(self.handler, other) def test_install(self): """Install one package""" self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, ['testpackage']) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(["testpackage"])) def test_install_multi_arch_current_arch(self): """We install a multi_arch package corresponding to current arch""" multi_arch_name = "testpackage:{}".format(tools.get_current_arch()) self.handler.install_bucket([multi_arch_name], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, [multi_arch_name]) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(["testpackage"])) def test_install_perm(self): """When we install one package, we first switch to root""" self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) os.seteuid.assert_called_once_with(0) os.setegid.assert_called_once_with(0) def test_install_return_error_if_no_perm(self): """Return an exception when we try to install and we can't switch to root""" os.seteuid.side_effect = PermissionError() self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertIsNotNone(self.done_callback.call_args[0][0].error) self.assertFalse(self.handler.is_bucket_installed(["testpackage"])) self.expect_warn_error = True def test_install_perm_switch_back_user(self): """When we install one package, we switch back to user at the end""" umake.network.requirements_handler.os.geteuid.return_value = 0 self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) # we call it twice and the latest is the user id self.assertEqual(os.seteuid.call_count, 2) self.assertEqual(os.seteuid.call_args, call(self.user_uid)) self.assertEqual(os.setegid.call_args, call(self.user_gid)) def test_install_progress(self): """Install one package and get progress feedback""" progress_callback = Mock() self.handler.install_bucket(["testpackage"], progress_callback, self.done_callback) self.wait_for_callback(self.done_callback) downloading_msg = self.count_number_progress_call(progress_callback.call_args_list, RequirementsHandler.STATUS_DOWNLOADING) installing_msg = self.count_number_progress_call(progress_callback.call_args_list, RequirementsHandler.STATUS_INSTALLING) self.assertTrue(downloading_msg > 1) self.assertTrue(installing_msg > 1) # the first download call is at 0% of progress. testpackage is 1byte to download on != xenial self.assertIn(progress_callback.call_args_list[0][0][0], [{'step': 0, 'pkg_size_download': 1, 'percentage': 0.0}, {'step': 0, 'pkg_size_download': 1698, 'percentage': 0.0}]) callfound = False for call in progress_callback.call_args_list: if call[0][0] == {'step': 1, 'percentage': 0.0}: callfound = True break self.assertTrue(callfound, "We expect to have one install step at 0% call in the list") def test_install_multiple_packages(self): """Install multiple packages in one shot""" self.handler.install_bucket(["testpackage", "testpackage0"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, ['testpackage', 'testpackage0']) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(["testpackage", "testpackage0"])) def test_install_multiple_packages_progress(self): """Install multiple packages in one shot and ensure that progress is global""" progress_callback = Mock() self.handler.install_bucket(["testpackage", "testpackage0"], progress_callback, self.done_callback) self.wait_for_callback(self.done_callback) downloading_msg = self.count_number_progress_call(progress_callback.call_args_list, RequirementsHandler.STATUS_DOWNLOADING) installing_msg = self.count_number_progress_call(progress_callback.call_args_list, RequirementsHandler.STATUS_INSTALLING) self.assertTrue(downloading_msg > 1) self.assertTrue(installing_msg > 1) # the first download call is at 0% of progress. testpackage is 1byte to download on != xenial self.assertIn(progress_callback.call_args_list[0][0][0], [{'step': 0, 'pkg_size_download': 1, 'percentage': 0.0}, {'step': 0, 'pkg_size_download': 3412, 'percentage': 0.0}]) def test_install_pending(self): """Appending two installations and wait for results. Only the first call should have progress""" done_callback0 = Mock() self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.handler.install_bucket(["testpackage0"], lambda x: "", done_callback0) self.wait_for_callback(self.done_callback) self.wait_for_callback(done_callback0) self.assertTrue(self.handler.is_bucket_installed(["testpackage", "testpackage0"])) def test_install_pending_order(self): """Installation order of pending requests are respected""" done_callback = Mock() done_callback.side_effect = self.done_callback done_callback0 = Mock() done_callback0.side_effect = self.done_callback ordered_progress_callback = Mock() progress_callback = Mock() progress_callback.side_effect = ordered_progress_callback progress_callback0 = Mock() progress_callback0.side_effect = ordered_progress_callback self.handler.install_bucket(["testpackage"], progress_callback, done_callback) self.handler.install_bucket(["testpackage0"], progress_callback0, done_callback0) self.wait_for_callback(done_callback) self.wait_for_callback(done_callback0) self.assertEqual(self.done_callback.call_args_list, [call(RequirementsHandler.RequirementsResult(bucket=['testpackage'], error=None)), call(RequirementsHandler.RequirementsResult(bucket=['testpackage0'], error=None))]) # we will get progress with 0, 1 (first bucket), 0, 1 (second bucket). So 4 progress signal status change current_status = RequirementsHandler.STATUS_DOWNLOADING current_status_change_count = 1 calls = ordered_progress_callback.call_args_list for current_call in calls[1:]: if current_call[0][0]['step'] != current_status: current_status = current_call[0][0]['step'] current_status_change_count += 1 self.assertEqual(current_status_change_count, 4) def test_install_pending_callback_not_mixed(self): """Callbacks are separated on pending requests""" done_callback = Mock() done_callback.side_effect = self.done_callback done_callback0 = Mock() done_callback0.side_effect = self.done_callback global_progress_callback = Mock() progress_callback = Mock() progress_callback.side_effect = global_progress_callback progress_callback0 = Mock() progress_callback0.side_effect = global_progress_callback self.handler.install_bucket(["testpackage"], progress_callback, done_callback) self.handler.install_bucket(["testpackage0"], progress_callback0, done_callback0) self.wait_for_callback(done_callback) self.wait_for_callback(done_callback0) self.assertTrue(progress_callback.call_count < global_progress_callback.call_count) self.assertTrue(progress_callback0.call_count < global_progress_callback.call_count) self.assertTrue(done_callback.call_count < self.done_callback.call_count) self.assertTrue(done_callback0.call_count < self.done_callback.call_count) def test_install_twice(self): """Test appending two installations and wait for results. Only the first call should have progress""" progress_callback = Mock() progress_second_callback = Mock() done_callback = Mock() self.handler.install_bucket(["testpackage"], progress_callback, done_callback) self.handler.install_bucket(["testpackage"], progress_second_callback, self.done_callback) self.wait_for_callback(done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_installed(["testpackage"])) self.assertFalse(progress_second_callback.called) def test_deps(self): """Installing one package, ensure the dep (even with auto_fix=False) is installed""" self.handler.install_bucket(["testpackage1"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_installed(["testpackage1", "testpackage"])) def test_fail(self): """An error is caught when asking for the impossible (installing 2 packages in conflicts)""" self.handler.install_bucket(["testpackage", "testpackage2"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertIsNotNone(self.done_callback.call_args[0][0].error) both_package_installed = self.handler.is_bucket_installed(["testpackage"]) and \ self.handler.is_bucket_installed(["testpackage2"]) self.assertFalse(both_package_installed) self.expect_warn_error = True def test_install_shadow_pkg(self): """We return an error if we try to install a none existing package""" self.handler.install_bucket(["foo"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertIsNotNone(self.done_callback.call_args[0][0].error) self.expect_warn_error = True def test_error_in_dpkg(self): """An error while installing a package is caught""" with open(self.dpkg, mode='w') as f: f.write("#!/bin/sh\nexit 1") # Simulate an error in dpkg self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertIsNotNone(self.done_callback.call_args[0][0].error) self.expect_warn_error = True def test_is_installed_bucket_installed(self): """Install bucket should return True if a bucket is installed""" self.handler.install_bucket(["testpackage", "testpackage1"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_installed(['testpackage', 'testpackage1'])) def test_is_installed_bucket_half_installed(self): """Install bucket shouldn't be considered installed if not fully installed""" self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertFalse(self.handler.is_bucket_installed(['testpackage', 'testpackage1'])) def test_is_installed_bucket_not_installed(self): """Install bucket should return False if a bucket is not installed""" self.assertFalse(self.handler.is_bucket_installed(['testpackage', 'testpackage1'])) def test_is_bucket_installed_multi_arch_current_arch(self): """Installed bucket should return True even if contains multi-arch part with current package""" self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_installed(["testpackage:{}".format(tools.get_current_arch())])) def test_is_bucket_installed_with_unavailable_package(self): """Bucket isn't installed if some package are even not in the cache""" self.assertFalse(self.handler.is_bucket_installed(["testpackagedoesntexist"])) def test_is_bucket_installed_with_unavailable_multiarch_package(self): """Bucket isn't installed if some multiarch package are even not in the cache""" self.assertFalse(self.handler.is_bucket_installed(["testpackagedoesntexist:foo"])) def test_is_bucket_installed_with_foreign_archs_package_not_installed(self): """After adding a foreign arch, test that the package is not installed and report so""" subprocess.call([self.dpkg, "--add-architecture", "foo"]) self.handler.cache.open() # reopen the cache with the new added architecture self.assertFalse(self.handler.is_bucket_installed(['testpackagefoo:foo'])) def test_is_bucket_uptodate_bucket_uptodate(self): """Up to date bucket is reported as such""" self.handler.install_bucket(["testpackage", "testpackage1"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_uptodate(['testpackage', 'testpackage1'])) def test_is_bucket_uptodate_bucket_not_installed(self): """Not installed bucket is not uptodate""" self.assertFalse(self.handler.is_bucket_uptodate(['testpackage', 'testpackage1'])) def test_is_bucket_uptodate_bucket_half_installed(self): """bucket shouldn't be considered up to date if not fully installed""" self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertFalse(self.handler.is_bucket_uptodate(['testpackage', 'testpackage1'])) def test_is_bucket_uptodate_multi_arch_current_arch(self): """Installed bucket should return as being uptodate even if contains multi-arch part with current package""" self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_uptodate(["testpackage:{}".format(tools.get_current_arch())])) def test_is_bucket_uptodate_with_unavailable_package(self): """Bucket isn't uptodate if some package are even not in the cache""" self.assertFalse(self.handler.is_bucket_uptodate(["testpackagedoesntexist"])) def test_is_bucket_uptodate_with_unavailable_multiarch_package(self): """Bucket isn't uptodate if some multiarch package are even not in the cache""" self.assertFalse(self.handler.is_bucket_uptodate(["testpackagedoesntexist:foo"])) def test_is_bucket_uptodate_with_foreign_archs(self): """After adding a foreign arch, test that the package is uptodate and report so""" subprocess.call([self.dpkg, "--add-architecture", "foo"]) self.handler.cache.open() # reopen the cache with the new added architecture self.handler.install_bucket(["testpackagefoo:foo"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(self.handler.is_bucket_uptodate(['testpackagefoo:foo'])) def test_is_bucket_uptodate_with_foreign_archs_package_not_installed(self): """After adding a foreign arch, test that the package is not uptodate and report so""" subprocess.call([self.dpkg, "--add-architecture", "foo"]) self.handler.cache.open() # reopen the cache with the new added architecture self.assertFalse(self.handler.is_bucket_uptodate(['testpackagefoo:foo'])) def test_is_bucket_uptodate_with_possible_upgrade(self): """If one package of the bucket can be upgraded, tell it's not up to date""" shutil.copy(os.path.join(self.apt_status_dir, "testpackage_installed_dpkg_status"), os.path.join(self.dpkg_dir, "status")) self.handler.cache.open() self.assertFalse(self.handler.is_bucket_uptodate(["testpackage"])) def test_is_bucket_available(self): """An available bucket on that platform is reported""" self.assertTrue(self.handler.is_bucket_available(['testpackage', 'testpackage1'])) def test_is_bucket_available_multi_arch_current_arch(self): """We return a package is available on the current platform""" self.assertTrue(self.handler.is_bucket_available(['testpackage:{}'.format(tools.get_current_arch())])) def test_unavailable_bucket(self): """An unavailable bucket on that platform is reported""" self.assertFalse(self.handler.is_bucket_available(['testpackage42', 'testpackage404'])) def test_is_bucket_available_foreign_archs(self): """After adding a foreign arch, test that the package is available on it""" subprocess.call([self.dpkg, "--add-architecture", "foo"]) self.handler.cache.open() # reopen the cache with the new added architecture self.assertTrue(self.handler.is_bucket_available(['testpackagefoo:foo', 'testpackage1'])) def test_is_bucket_unavailable_with_foreign_archs(self): """After adding a foreign arch, test that the package is unavailable and report so""" subprocess.call([self.dpkg, "--add-architecture", "foo"]) self.handler.cache.open() # reopen the cache with the new added architecture self.assertFalse(self.handler.is_bucket_available(['testpackagebar:foo', 'testpackage1'])) def test_bucket_unavailable_but_foreign_archs_no_added(self): """Bucket is set as available when foreign arch not added""" self.assertTrue(self.handler.is_bucket_available(['testpackagefoo:foo', 'testpackage1'])) def test_bucket_unavailable_foreign_archs_no_added_another_package_not_available(self): """Bucket is set as unavailable when foreign arch not added, but another package on current arch is unavailable""" self.assertFalse(self.handler.is_bucket_available(['testpackagefoo:foo', 'testpackage123'])) def test_apt_cache_not_ready(self): """When the first apt.Cache() access tells it's not ready, we wait and recover""" origin_open = self.handler.cache.open raise_returned = False def cache_call(*args, **kwargs): nonlocal raise_returned if raise_returned: return origin_open() else: raise_returned = True raise SystemError with patch.object(self.handler.cache, 'open', side_effect=cache_call) as openaptcache_mock: self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(openaptcache_mock.call_count, 2) def test_upgrade(self): """Upgrade one package already installed""" shutil.copy(os.path.join(self.apt_status_dir, "testpackage_installed_dpkg_status"), os.path.join(self.dpkg_dir, "status")) self.handler.cache.open() self.assertTrue(self.handler.is_bucket_installed(["testpackage"])) self.assertEqual(self.handler.cache["testpackage"].installed.version, "0.0.0") self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, ['testpackage']) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(["testpackage"])) self.assertEqual(self.handler.cache["testpackage"].installed.version, "0.0.1") def test_one_install_one_upgrade(self): """Install and Upgrade one package in the same bucket""" shutil.copy(os.path.join(self.apt_status_dir, "testpackage_installed_dpkg_status"), os.path.join(self.dpkg_dir, "status")) self.handler.cache.open() self.assertTrue(self.handler.is_bucket_installed(["testpackage"])) self.assertEqual(self.handler.cache["testpackage"].installed.version, "0.0.0") self.assertFalse(self.handler.is_bucket_installed(["testpackage0"])) self.handler.install_bucket(["testpackage", "testpackage0"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, ['testpackage', 'testpackage0']) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(["testpackage", "testpackage0"])) self.assertEqual(self.handler.cache["testpackage"].installed.version, "0.0.1") def test_install_with_foreign_foreign_arch_added(self): """Install packages with a foreign arch added""" subprocess.call([self.dpkg, "--add-architecture", "foo"]) self.handler.cache.open() # reopen the cache with the new added architecture bucket = ["testpackagefoo:foo", "testpackage1"] with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.check_output.side_effect = subprocess.check_output self.handler.install_bucket(bucket, lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertFalse(subprocess_mock.call.called) self.assertEqual(self.done_callback.call_args[0][0].bucket, bucket) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(bucket)) def test_install_with_foreign_foreign_arch_not_added(self): """Install packages with a foreign arch, while the foreign arch wasn't added""" bucket = ["testpackagefoo:foo", "testpackage1"] self.handler.install_bucket(bucket, lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, bucket) self.assertIsNone(self.done_callback.call_args[0][0].error) self.assertTrue(self.handler.is_bucket_installed(bucket)) def test_install_with_foreign_foreign_arch_add_fails(self): """Install packages with a foreign arch, where adding a foreign arch fails""" bucket = ["testpackagefoo:foo", "testpackage1"] with patch("umake.tools.subprocess") as subprocess_mock: subprocess_mock.call.return_value = 1 self.handler.install_bucket(bucket, lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertTrue(subprocess_mock.call.called) self.assertFalse(self.handler.is_bucket_installed(bucket)) self.expect_warn_error = True def test_cant_change_seteuid(self): """Not being able to change the euid to root returns an error""" os.seteuid.side_effect = PermissionError() self.handler.install_bucket(["testpackage"], lambda x: "", self.done_callback) self.wait_for_callback(self.done_callback) self.assertEqual(self.done_callback.call_args[0][0].bucket, ['testpackage']) self.assertIsNotNone(self.done_callback.call_args[0][0].error) self.assertFalse(self.handler.is_bucket_installed(["testpackage"])) self.expect_warn_error = True def test_or_option_none_installed(self): self.assertFalse(self.handler.is_bucket_installed(["testpackage | testpackage0"])) def test_or_option_first_installed(self): test_bucket = ["testpackage | testpackage1 | testpackage0"] shutil.copy(os.path.join(self.apt_status_dir, "testpackage_installed_dpkg_status"), os.path.join(self.dpkg_dir, "status")) self.handler.cache.open() self.assertTrue(self.handler.is_bucket_installed(test_bucket)) self.assertEqual(test_bucket, ['testpackage']) def test_or_option_second_installed(self): test_bucket = ["testpackage0 | testpackage | testpackage1", "testpackage2"] shutil.copy(os.path.join(self.apt_status_dir, "testpackage_installed_dpkg_status"), os.path.join(self.dpkg_dir, "status")) self.handler.cache.open() self.assertTrue(self.handler.is_bucket_installed(test_bucket)) self.assertEqual(test_bucket, ['testpackage2', 'testpackage']) def test_or_option_third_installed(self): test_bucket = ["testpackage0 | testpackage1 | testpackage", "testpackage2"] shutil.copy(os.path.join(self.apt_status_dir, "testpackage_installed_dpkg_status"), os.path.join(self.dpkg_dir, "status")) self.handler.cache.open() self.assertTrue(self.handler.is_bucket_installed(test_bucket)) self.assertEqual(test_bucket, ['testpackage2', 'testpackage']) def test_or_option_is_first_available(self): test_bucket = ["testpackage | testpackage42", "testpackage1"] self.handler.cache.open() self.assertTrue(self.handler.is_bucket_available(test_bucket)) self.assertEqual(test_bucket, ['testpackage1', 'testpackage']) def test_or_option_is_second_available(self): test_bucket = ["testpackage42 | testpackage"] self.handler.cache.open() self.assertTrue(self.handler.is_bucket_available(test_bucket)) self.assertEqual(test_bucket, ['testpackage']) def test_or_option_is_none_available(self): self.assertFalse(self.handler.is_bucket_available(['testpackage42 | testpackage404'])) def test_or_option_both_available(self): test_bucket = ['testpackage | testpackage0', 'testpackage1'] self.handler.cache.open() self.assertTrue(self.handler.is_bucket_available(test_bucket)) self.assertEqual(test_bucket, ['testpackage1', 'testpackage']) ubuntu-make-16.11.1ubuntu1/tests/small/test_download_center.py0000664000000000000000000006340613013560574021401 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the download center module using a local server""" from enum import Enum import os from os.path import join, getsize from time import time from unittest.mock import Mock, call from ..tools import get_data_dir, CopyingMock, LoggedTestCase from ..tools.local_server import LocalHttp from umake.network.download_center import DownloadCenter, DownloadItem from umake.tools import ChecksumType, Checksum class TestDownloadCenter(LoggedTestCase): """This will test the download center by sending one or more download requests""" server = None @classmethod def setUpClass(cls): super().setUpClass() cls.server_dir = join(get_data_dir(), "server-content") cls.server = LocalHttp(cls.server_dir) @classmethod def tearDownClass(cls): super().tearDownClass() cls.server.stop() def setUp(self): super().setUp() self.callback = Mock() self.fd_to_close = [] def tearDown(self): super().tearDown() for fd in self.fd_to_close: fd.close() def build_server_address(self, path, localhost=False): """build server address to path to get requested""" return "{}/{}".format(self.server.get_address(localhost=localhost), path) def wait_for_callback(self, mock_function_to_be_called): """wait for the callback to be called until a timeout. Add temp files to the clean file list afterwards""" timeout = time() + 5 while not mock_function_to_be_called.called: if time() > timeout: raise(BaseException("Function not called within 5 seconds")) for calls in mock_function_to_be_called.call_args[0]: for request in calls: if calls[request].fd: self.fd_to_close.append(calls[request].fd) if calls[request].buffer: self.fd_to_close.append(calls[request].buffer) def test_download(self): """we deliver one successful download""" filename = "simplefile" url = self.build_server_address(filename) request = DownloadItem(url, None) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertTrue('.' not in result.fd.name, result.fd.name) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_redirect_download(self): """we deliver one successful download after being redirected""" filename = "simplefile" # We add a suffix to make the server redirect us. url = self.build_server_address(filename + "-redirect") request = DownloadItem(url, None) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) self.assertEqual(result.final_url, self.build_server_address(filename)) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_header_download(self): """we deliver one successful download with some headers""" filename = "simplefile" url = self.build_server_address(filename + '-headers?header=test') request = DownloadItem(url, headers={"header": "test"}) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertTrue('.' not in result.fd.name, result.fd.name) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_cookies(self): """Test handing of outgoing and incoming cookies.""" filename = "simplefile" url = self.build_server_address(filename) # The server is rigged to inc the 'int' cookie by one. cookies = {'int': '5'} request = DownloadItem(url, None, cookies=cookies) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) self.assertEqual('6', result.cookies['int']) def test_content_encoding(self): """Ensure we perform (or don't) content decoding properly.""" # Use an existing .gz file, at data/server-content/www.eclipse.org/.../eclipse-standard-luna-R-linux-gtk.tar.gz filename = "www.eclipse.org/technology/epp/downloads/release/version/"\ "point_release/eclipse-java-linux-gtk.tar.gz" length = 10240 compressed_length = 266 url = self.build_server_address(filename + '-setheaders?content-encoding=gzip') request = DownloadItem(url) DownloadCenter([request], self.callback, download=False) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) self.assertEqual(length, len(result.buffer.getvalue())) # Reset the callback mock. self.callback = Mock() request = DownloadItem(url, ignore_encoding=True) DownloadCenter([request], self.callback, download=False) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) self.assertEqual(compressed_length, len(result.buffer.getvalue())) def test_download_keep_extensions(self): """we deliver successful downloads keeping the extension""" filename = "android-studio-fake.tgz" url = self.build_server_address(filename) request = DownloadItem(url, None) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb'): self.assertTrue(result.fd.name.endswith('.tgz'), result.fd.name) def test_download_with_md5(self): """we deliver once successful download, matching md5sum""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.md5, '268a5059001855fef30b4f95f82044ed'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_download_with_sha1sum(self): """we deliver once successful download, matching sha1sum""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.sha1, '0562f08aef399135936d6fb4eb0cc7bc1890d5b4'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_download_with_sha256sum(self): """we deliver once successful download, matching sha256sum""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.sha256, 'b1b113c6ed8ab3a14779f7c54179eac2b87d39fcebbf65a50556b8d68caaa2fb'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_download_with_sha512sum(self): """we deliver once successful download, matching sha512sum""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.sha512, '74e20d520ba4ecfdb59d98ac213deccecf591c9c6bfc5996ac158ab6facd6611cce7dd2' '2120b63ebe9217f159506f352ce0ee6c0c2a1d200841ae21635dc5f9a'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_download_with_no_checksum_value(self): """we deliver one successful download with a checksum type having no value""" filename = "simplefile" url = self.build_server_address(filename) request = DownloadItem(url, Checksum(ChecksumType.md5, None)) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertTrue('.' not in result.fd.name, result.fd.name) self.assertIsNone(result.buffer) self.assertIsNone(result.error) def test_download_with_progress(self): """we deliver progress hook while downloading""" filename = "simplefile" filesize = getsize(join(self.server_dir, filename)) report = CopyingMock() request = DownloadItem(self.build_server_address(filename), None) DownloadCenter([request], self.callback, report=report) self.wait_for_callback(self.callback) self.assertEqual(report.call_count, 2) self.assertEqual(report.call_args_list, [call({self.build_server_address(filename): {'size': filesize, 'current': 0}}), call({self.build_server_address(filename): {'size': filesize, 'current': filesize}})]) def test_download_with_multiple_progress(self): """we deliver multiple progress hooks on bigger files""" filename = "biggerfile" filesize = getsize(join(self.server_dir, filename)) report = CopyingMock() request = DownloadItem(self.build_server_address(filename), None) dl_center = DownloadCenter([request], self.callback, report=report) self.wait_for_callback(self.callback) self.assertEqual(report.call_count, 3) self.assertEqual(report.call_args_list, [call({self.build_server_address(filename): {'size': filesize, 'current': 0}}), call({self.build_server_address(filename): {'size': filesize, 'current': dl_center.BLOCK_SIZE}}), call({self.build_server_address(filename): {'size': filesize, 'current': filesize}})]) def test_multiple_downloads(self): """we deliver more than on download in parallel""" requests = [DownloadItem(self.build_server_address("biggerfile"), None), DownloadItem(self.build_server_address("simplefile"), None)] DownloadCenter(requests, self.callback) self.wait_for_callback(self.callback) # ensure we saw 2 different requests callback_args, callback_kwargs = self.callback.call_args map_result = callback_args[0] self.assertIn(self.build_server_address("biggerfile"), map_result) self.assertIn(self.build_server_address("simplefile"), map_result) # ensure each temp file corresponds to the source content for filename in ("biggerfile", "simplefile"): with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), map_result[self.build_server_address(filename)].fd.read()) self.assertEqual(self.callback.call_count, 1, "Global done callback is only called once") def test_multiple_downloads_with_reports(self): """we deliver more than on download in parallel""" requests = [DownloadItem(self.build_server_address("biggerfile"), None), DownloadItem(self.build_server_address("simplefile"), None)] report = CopyingMock() DownloadCenter(requests, self.callback, report=report) self.wait_for_callback(self.callback) self.assertEqual(report.call_count, 5) # ensure that first call only contains one file callback_args, callback_kwargs = report.call_args_list[0] map_result = callback_args[0] self.assertEqual(len(map_result), 1, str(map_result)) # ensure that last call is what we expect result_dict = {} for filename in ("biggerfile", "simplefile"): file_size = getsize(join(self.server_dir, filename)) result_dict[self.build_server_address(filename)] = {'size': file_size, 'current': file_size} self.assertEqual(report.call_args, call(result_dict)) self.assertEqual(self.callback.call_count, 1, "Global done callback is only called once") def test_404_url(self): """we return an error for a request including a 404 url""" request = DownloadItem(self.build_server_address("does_not_exist"), None) DownloadCenter([request], self.callback) self.wait_for_callback(self.callback) # no download means the file isn't in the result callback_args, callback_kwargs = self.callback.call_args result = callback_args[0][self.build_server_address("does_not_exist")] self.assertIn("404", result.error) self.assertIn("File not found", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True self.assertEqual(self.callback.call_count, 1, "Global done callback is only called once") def test_multiple_with_one_404_url(self): """we raise an error when we try to download 404 urls""" requests = [DownloadItem(self.build_server_address("does_not_exist"), None), DownloadItem(self.build_server_address("simplefile"), None)] DownloadCenter(requests, self.callback) self.wait_for_callback(self.callback) # we should have the two content, one in error callback_args, callback_kwargs = self.callback.call_args map_result = callback_args[0] self.assertEqual(len(map_result), 2, str(map_result)) self.assertIsNotNone(map_result[self.build_server_address("does_not_exist")].error) self.assertIsNotNone(map_result[self.build_server_address("simplefile")].fd) self.expect_warn_error = True self.assertEqual(self.callback.call_count, 1, "Global done callback is only called once") def test_in_memory_download(self): """we deliver download on memory objects""" filename = "simplefile" url = self.build_server_address(filename) request = DownloadItem(url, None) DownloadCenter([request], self.callback, download=False) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.buffer.read()) self.assertIsNone(result.fd) self.assertIsNone(result.error) def test_unsupported_protocol(self): """Raises an exception when trying to download for an unsupported protocol""" filename = "simplefile" url = self.build_server_address(filename).replace('http', 'sftp') request = DownloadItem(url, None) DownloadCenter([request], self.callback, download=False) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertIn("Protocol not supported", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True def test_download_with_wrong_md5(self): """we raise an error if we don't have the correct md5sum""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.md5, 'AAAAA'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertIn("Corrupted download", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True def test_download_with_wrong_sha1(self): """we raise an error if we don't have the correct sha1""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.sha1, 'AAAAA'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertIn("Corrupted download", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True def test_download_with_wrong_sha256(self): """we raise an error if we don't have the correct sha256""" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(ChecksumType.sha256, 'AAAAA'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertIn("Corrupted download", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True def test_download_with_no_size(self): """we deliver one successful download, even if size isn't provided. Progress returns -1 though""" filename = "simplefile-with-no-content-length" url = self.build_server_address(filename) request = DownloadItem(url, None) report = CopyingMock() DownloadCenter([request], self.callback, report=report) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) self.assertEqual(report.call_count, 2) self.assertEqual(report.call_args_list, [call({self.build_server_address(filename): {'size': -1, 'current': 0}}), call({self.build_server_address(filename): {'size': -1, 'current': 8192}})]) def test_download_with_wrong_checksumtype(self): """we raise an error if we don't have a support checksum type""" class WrongChecksumType(Enum): didrocksha = "didrocksha" filename = "simplefile" request = self.build_server_address(filename) DownloadCenter([DownloadItem(request, Checksum(WrongChecksumType.didrocksha, 'AAAAA'))], self.callback) self.wait_for_callback(self.callback) result = self.callback.call_args[0][0][request] self.assertIn("Unsupported checksum type", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True class TestDownloadCenterSecure(LoggedTestCase): """This will test the download center in secure mode by sending one or more download requests""" server = None @classmethod def setUpClass(cls): super().setUpClass() cls.server_dir = join(get_data_dir(), "server-content") cls.server = LocalHttp(cls.server_dir, use_ssl=["localhost"]) @classmethod def tearDownClass(cls): super().tearDownClass() cls.server.stop() def setUp(self): super().setUp() self.callback = Mock() self.fd_to_close = [] def tearDown(self): super().tearDown() for fd in self.fd_to_close: fd.close() def test_download(self): """we deliver one successful download under ssl with known cert""" filename = "simplefile" # The host name is important here, since we verify it, so request # the localhost address. url = TestDownloadCenter.build_server_address(self, filename, True) request = DownloadItem(url, None) # prepare the cert and set it as the trusted system context os.environ['REQUESTS_CA_BUNDLE'] = join(get_data_dir(), 'localhost.pem') try: DownloadCenter([request], self.callback) TestDownloadCenter.wait_for_callback(self, self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) with open(os.path.join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) finally: del os.environ['REQUESTS_CA_BUNDLE'] def test_redirect_download(self): """we deliver one successful download after being redirected""" filename = "simplefile" # We add a suffix to make the server redirect us. url = TestDownloadCenter.build_server_address(self, filename + "-redirect", localhost=True) request = DownloadItem(url, None) os.environ['REQUESTS_CA_BUNDLE'] = join(get_data_dir(), 'localhost.pem') try: DownloadCenter([request], self.callback) TestDownloadCenter.wait_for_callback(self, self.callback) result = self.callback.call_args[0][0][url] self.assertTrue(self.callback.called) self.assertEqual(self.callback.call_count, 1) self.assertEqual(result.final_url, TestDownloadCenter.build_server_address(self, filename, localhost=True)) with open(os.path.join(self.server_dir, filename), 'rb') as file_on_disk: self.assertEqual(file_on_disk.read(), result.fd.read()) self.assertIsNone(result.buffer) self.assertIsNone(result.error) finally: del os.environ['REQUESTS_CA_BUNDLE'] def test_with_invalid_certificate(self): """we error on invalid ssl certificate""" filename = "simplefile" url = TestDownloadCenter.build_server_address(self, filename) request = DownloadItem(url, None) DownloadCenter([request], self.callback) TestDownloadCenter.wait_for_callback(self, self.callback) result = self.callback.call_args[0][0][url] self.assertIn("CERTIFICATE_VERIFY_FAILED", result.error) self.assertIsNone(result.buffer) self.assertIsNone(result.fd) self.expect_warn_error = True ubuntu-make-16.11.1ubuntu1/tests/small/test_interactions.py0000664000000000000000000003311313013560574020724 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests the various umake available interactions""" from ..tools import LoggedTestCase from umake.tools import InputError from umake.interactions import Choice, TextWithChoices, LicenseAgreement, InputText, YesNo, DisplayMessage,\ UnknownProgress from unittest.mock import Mock class TestInteractions(LoggedTestCase): """Test various interactions""" def test_choices(self): """We can instantiate with a choices interactions""" choices = [Choice(0, "Choice0", lambda: ""), Choice(1, "Choice1", lambda: ""), Choice(2, "Choice2", lambda: "")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choices, choices) self.assertEqual(inter.content, "Foo Content") def test_choices_with_text_shorcut(self): """We can instantiate choices interactions with shortcut""" choices = [Choice(0, "Choice0", lambda: "", txt_shorcut="A"), Choice(1, "Choice1", lambda: "", txt_shorcut="B"), Choice(2, "Choice2", lambda: "", txt_shorcut="C")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choices, choices) self.assertEqual(inter.content, "Foo Content") def test_choices_with_default(self): """We can instantiate choices interactions with a default""" choices = [Choice(0, "Choice0", lambda: ""), Choice(1, "Choice1", lambda: "", is_default=True), Choice(2, "Choice2", lambda: "")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choices, choices) self.assertEqual(inter.content, "Foo Content") def test_choices_prompt(self): """We give a prompt for normal choice""" choices = [Choice(0, "Choice0", lambda: ""), Choice(1, "Choice1", lambda: ""), Choice(2, "Choice2", lambda: "")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.prompt, "Foo Content [Choice0/Choice1/Choice2] ") def test_choices_prompt_with_newline(self): """We give a prompt with newline before options if requested""" choices = [Choice(0, "Choice0", lambda: ""), Choice(1, "Choice1", lambda: ""), Choice(2, "Choice2", lambda: "")] inter = TextWithChoices("Foo Content", choices, newline_before_option=True) self.assertEqual(inter.prompt, "Foo Content\n[Choice0/Choice1/Choice2] ") def test_choices_prompt_with_txt_shortcut(self): """We give a prompt with txt shortcut if any""" choices = [Choice(0, "Choice0", lambda: "", txt_shorcut="A"), Choice(1, "Choice1", lambda: "", txt_shorcut="B"), Choice(2, "Choice2", lambda: "", txt_shorcut="c")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.prompt, "Foo Content [Choice0 (A)/Choice1 (B)/Choice2 (c)] ") def test_choices_prompt_with_partial_txt_shortcut(self): """We give a prompt, some choices having txt shortcut""" choices = [Choice(0, "Choice0", lambda: "", txt_shorcut="A"), Choice(1, "Choice1", lambda: ""), Choice(2, "Choice2", lambda: "", txt_shorcut="c")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.prompt, "Foo Content [Choice0 (A)/Choice1/Choice2 (c)] ") def test_instantiate_with_multiple_defaults_raises(self): """Instantiating with multiple defaults raises""" choices = [Choice(0, "Choice0", lambda: "", is_default=True), Choice(1, "Choice1", lambda: "", is_default=True), Choice(2, "Choice2", lambda: "")] self.assertRaises(BaseException, TextWithChoices, "Foo Content", choices) self.expect_warn_error = True def test_choices_choose_run_right_callback(self): """Choose call the correct callback""" callback1 = Mock() callback2 = Mock() choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", callback1), Choice(2, "Choice2", callback2)] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(choice_id=1), callback1.return_value) self.assertEqual(inter.choose(choice_id=2), callback2.return_value) def test_choices_choose_with_shorcut_run_right_callback(self): """Choose with text shortcut calls the correct callback""" callback1 = Mock() callback2 = Mock() choices = [Choice(0, "Choice0", Mock(), txt_shorcut="A"), Choice(1, "Choice1", callback1, txt_shorcut="B"), Choice(2, "Choice2", callback2, txt_shorcut="C")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(answer='B'), callback1.return_value) self.assertEqual(inter.choose(answer='C'), callback2.return_value) def test_choices_choose_with_label_run_right_callback(self): """Choose with label calls the correct callback""" callback1 = Mock() callback2 = Mock() choices = [Choice(0, "Choice0", Mock(), txt_shorcut="A"), Choice(1, "Choice1", callback1, txt_shorcut="B"), Choice(2, "Choice2", callback2, txt_shorcut="C")] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(answer='Choice1'), callback1.return_value) self.assertEqual(inter.choose(answer='Choice2'), callback2.return_value) def test_choices_choose_with_partial_shorcut_run_right_callback(self): """Choose with some having text shortcut calls the correct callback""" callback1 = Mock() choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", callback1, txt_shorcut="B"), Choice(2, "Choice2", Mock())] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(answer='B'), callback1.return_value) def test_choices_choose_with_shorcut_no_right_casse(self): """Choose with shortcut without respecting the casse""" callback1 = Mock() choices = [Choice(0, "Choice0", Mock(), txt_shorcut="A"), Choice(1, "Choice1", callback1, txt_shorcut="B"), Choice(2, "Choice2", Mock())] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(answer='b'), callback1.return_value) def test_choices_choose_with_label_no_right_casse(self): """Choose with label without respecting the casse""" callback1 = Mock() choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", callback1), Choice(2, "Choice2", Mock())] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(answer='chOIce1'), callback1.return_value) def test_reject_invalid_choices(self): """TestChoice with Choices with the same id raises""" choices = [Choice(0, "Choice0", lambda: ""), Choice(1, "Choice1", lambda: ""), Choice(0, "Choice2", lambda: "")] self.assertRaises(BaseException, TextWithChoices, "Foo Content", choices) self.expect_warn_error = True def test_choices_wrong_choice_id_raise(self): """Wrong choice_id raises an exception""" callback1 = Mock() callback2 = Mock() choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", callback1), Choice(2, "Choice2", callback2)] inter = TextWithChoices("Foo Content", choices) self.assertRaises(InputError, inter.choose, choice_id=3) def test_choices_wrong_txt_shortcut_raise(self): """Wrong txt shortcut raises an exception""" choices = [Choice(0, "Choice0", Mock(), txt_shorcut='A'), Choice(1, "Choice1", Mock(), txt_shorcut='B'), Choice(2, "Choice2", Mock(), txt_shorcut='C')] inter = TextWithChoices("Foo Content", choices) self.assertRaises(InputError, inter.choose, answer='Z') def test_choices_wrong_label_raise(self): """Wrong label answer raises an exception""" choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", Mock()), Choice(2, "Choice2", Mock())] inter = TextWithChoices("Foo Content", choices) self.assertRaises(InputError, inter.choose, answer='abc') def test_choices_choose_default(self): """Choices with a default without any answer return callback""" callback1 = Mock() choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", callback1, is_default=True), Choice(2, "Choice2", Mock())] inter = TextWithChoices("Foo Content", choices) self.assertEqual(inter.choose(), callback1.return_value) def test_choices_choose_no_default_raises(self): """We raise an exception if there is no default and we choose without any answer""" choices = [Choice(0, "Choice0", Mock()), Choice(1, "Choice1", Mock()), Choice(2, "Choice2", Mock())] inter = TextWithChoices("Foo Content", choices) self.assertRaises(InputError, inter.choose) def test_license_agreement(self): """We can instantiate a license agreement interaction""" callback_yes = Mock() callback_no = Mock() inter = LicenseAgreement("License content", callback_yes, callback_no) self.assertEqual(inter.content, "License content") self.assertEqual(len(inter.choices), 2, str(inter.choices)) def test_license_agreement_choice(self): """We have right callbacks called in license choices""" callback_yes = Mock() callback_no = Mock() inter = LicenseAgreement("License content", callback_yes, callback_no) self.assertEqual(inter.choose(choice_id=0), callback_yes.return_value) self.assertEqual(inter.choose(choice_id=1), callback_no.return_value) self.assertEqual(inter.choose(answer='a'), callback_yes.return_value) self.assertEqual(inter.choose(answer='N'), callback_no.return_value) self.assertEqual(inter.choose(), callback_no.return_value) def test_license_agreement_input(self): """We return a license agreement input""" inter = LicenseAgreement("License content", lambda: "", lambda: "") self.assertEqual(inter.input, "[I Accept (a)/I don't accept (N)] ") def test_input_text(self): """We can instantiate an input text""" inter = InputText("Content", lambda: "") self.assertEqual(inter.content, "Content") self.assertEqual(inter.default_input, "") def test_input_text_with_default_input(self): """We can instantiate an input text with a default input""" inter = InputText("Content", lambda: "", default_input="This is a default input") self.assertEqual(inter.default_input, "This is a default input") def test_input_text_callback(self): """An input text runs callback with the result as argument""" callback_fn = Mock() inter = InputText("Content", callback_fn) inter.run_callback("Foo Bar Baz") callback_fn.assert_called_once_with("Foo Bar Baz") def test_yesno(self): """We can instantiate a YesNo""" inter = YesNo("Content?", lambda: "", lambda: "") self.assertEqual(inter.content, "Content?") self.assertEqual(len(inter.choices), 2, str(inter.choices)) self.assertEqual(inter.prompt, "Content? [Yes (y)/No (N)] ") def test_yesno_choose_default(self): """Default is No""" yes_callback = Mock() no_callback = Mock() inter = YesNo("Content?", yes_callback, no_callback) inter.choose("") self.assertTrue(no_callback.called) self.assertFalse(yes_callback.called) def test_yesno_choose_default_overriden(self): """Default is No""" yes_callback = Mock() no_callback = Mock() inter = YesNo("Content?", yes_callback, no_callback, default_is_yes=True) inter.choose("") self.assertTrue(yes_callback.called) self.assertFalse(no_callback.called) def test_yesno_run_answers(self): """Yes runs yes in different ways""" yes_callback = Mock() no_callback = Mock() inter = YesNo("Content?", yes_callback, no_callback) self.assertEqual(inter.choose(choice_id=0), yes_callback.return_value) self.assertEqual(inter.choose(choice_id=1), no_callback.return_value) self.assertEqual(inter.choose(answer='Y'), yes_callback.return_value) self.assertEqual(inter.choose(answer='N'), no_callback.return_value) self.assertEqual(inter.choose(answer='yEs'), yes_callback.return_value) self.assertEqual(inter.choose(answer='nO'), no_callback.return_value) def test_display_message(self): """We can instantiate a message display""" inter = DisplayMessage("Content") self.assertEqual(inter.text, "Content") def test_unknown_progress(self): """We can instantiate an unknown progress""" def foo(): yield inter = UnknownProgress(foo) inter.bar = "BarElement" self.assertEqual(inter.bar, "BarElement") ubuntu-make-16.11.1ubuntu1/tests/small/test_ui.py0000664000000000000000000001421113013560574016635 0ustar # -*- coding: utf-8 -*- # Copyright (C) 2014 Canonical # # Authors: # Didier Roche # # 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; version 3. # # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Tests for the generic ui module""" from concurrent import futures from gi.repository import GLib from time import time from unittest.mock import Mock, patch from ..tools import LoggedTestCase import threading from umake.tools import MainLoop, Singleton from umake.ui import UI class TestUI(LoggedTestCase): """This will test the UI generic module""" def setUp(self): super().setUp() self.mockUIPlug = Mock() self.mockUIPlug._display.side_effect = self.display_UIPlug self.contentType = Mock() self.ui = UI(self.mockUIPlug) self.mainloop_object = MainLoop() self.mainloop_thread = None self.function_thread = None self.display_thread = None self.time_display_call = 0 def tearDown(self): Singleton._instances = {} super().tearDown() # function that will complete once the mainloop is started def wait_for_mainloop_function(self): timeout_time = time() + 5 while not self.mainloop_object.mainloop.is_running(): if time() > timeout_time: raise(BaseException("Mainloop not started in 5 seconds")) def wait_for_mainloop_shutdown(self): timeout_time = time() + 5 while self.mainloop_object.mainloop.is_running(): if time() > timeout_time: raise(BaseException("Mainloop not stopped in 5 seconds")) def get_mainloop_thread(self): self.mainloop_thread = threading.current_thread().ident def start_glib_mainloop(self): # quit after 5 seconds if nothing made the mainloop to end GLib.timeout_add_seconds(5, self.mainloop_object.mainloop.quit) GLib.idle_add(self.get_mainloop_thread) self.mainloop_object.run() def display_UIPlug(self, contentType): """handler to mock _display and save the current thread""" self.time_display_call = time() self.assertEqual(self.contentType, contentType) self.display_thread = threading.current_thread().ident self.mainloop_object.quit(raise_exception=False) def test_singleton(self): """Ensure we are delivering a singleton for UI""" other = UI(self.mockUIPlug) self.assertEqual(self.ui, other) def test_return_to_mainscreen(self): """We call the return to main screen on the UIPlug""" UI.return_main_screen() self.assertTrue(self.mockUIPlug._return_main_screen.called) @patch("umake.tools.sys") def test_call_display(self, mocksys): """We call the display method from the UIPlug""" UI.display(self.contentType) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() self.assertTrue(self.mockUIPlug._display.called) self.assertIsNotNone(self.mainloop_thread) self.assertIsNotNone(self.display_thread) self.assertEqual(self.mainloop_thread, self.display_thread) @patch("umake.tools.sys") def test_call_display_other_thread(self, mocksys): """We call the display method on UIPlug in the main thread from another thread""" def run_display(future): self.function_thread = threading.current_thread().ident UI.display(self.contentType) executor = futures.ThreadPoolExecutor(max_workers=1) future = executor.submit(self.wait_for_mainloop_function) future.add_done_callback(run_display) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() self.assertTrue(self.mockUIPlug._display.called) self.assertIsNotNone(self.mainloop_thread) self.assertIsNotNone(self.function_thread) self.assertIsNotNone(self.display_thread) self.assertNotEqual(self.mainloop_thread, self.function_thread) self.assertEqual(self.mainloop_thread, self.display_thread) @patch("umake.tools.sys") def test_call_delayed_display(self, mocksys): """We call the display method from the UIPlug in delayed_display with 50ms waiting""" UI.delayed_display(self.contentType) now = time() self.start_glib_mainloop() self.wait_for_mainloop_shutdown() self.assertTrue(self.mockUIPlug._display.called) self.assertIsNotNone(self.mainloop_thread) self.assertIsNotNone(self.display_thread) self.assertEqual(self.mainloop_thread, self.display_thread) self.assertTrue(self.time_display_call - now > 0.05) @patch("umake.tools.sys") def test_call_delayed_display_from_other_thread(self, mocksys): """We call the display method from the UIPlug in delayed_display with 50ms waiting, even on other thread""" now = 0 def run_display(future): nonlocal now self.function_thread = threading.current_thread().ident now = time() UI.delayed_display(self.contentType) executor = futures.ThreadPoolExecutor(max_workers=1) future = executor.submit(self.wait_for_mainloop_function) future.add_done_callback(run_display) self.start_glib_mainloop() self.wait_for_mainloop_shutdown() self.assertTrue(self.mockUIPlug._display.called) self.assertIsNotNone(self.mainloop_thread) self.assertIsNotNone(self.function_thread) self.assertIsNotNone(self.display_thread) self.assertNotEqual(self.mainloop_thread, self.function_thread) self.assertEqual(self.mainloop_thread, self.display_thread) self.assertTrue(self.time_display_call - now > 0.05) ubuntu-make-16.11.1ubuntu1/debian/0000775000000000000000000000000013135606404013556 5ustar ubuntu-make-16.11.1ubuntu1/debian/copyright0000664000000000000000000000166513013560574015523 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Ubuntu Make Source: https://github.com/ubuntu/ubuntu-make Files: * Copyright: (C) 2014 Canonical License: GPL-3 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; version 3 of the License. . 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 package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA . The full text of the GPL is distributed in /usr/share/common-licenses/GPL-3 on Debian systems. ubuntu-make-16.11.1ubuntu1/debian/ubuntu-make.postinst0000664000000000000000000000036713013560574017630 0ustar #!/bin/sh set -e case "$1" in configure) register-python-argcomplete3 umake > /etc/bash_completion.d/umake ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 ubuntu-make-16.11.1ubuntu1/debian/ubuntu-make.manpages0000664000000000000000000000001713013560574017530 0ustar debian/umake.1 ubuntu-make-16.11.1ubuntu1/debian/ubuntu-make.postrm0000664000000000000000000000042613013560574017265 0ustar #!/bin/sh set -e case "$1" in purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) rm -f /etc/bash_completion.d/umake ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 ubuntu-make-16.11.1ubuntu1/debian/changelog0000664000000000000000000010543213135606404015435 0ustar ubuntu-make (16.11.1ubuntu1) artful; urgency=medium * Fix ZipFileWithPerm compatibility with internal 3.6 API. -- Dimitri John Ledkov Tue, 25 Jul 2017 10:18:30 +0100 ubuntu-make (16.11.1) zesty; urgency=medium * Enable small tests passing on yakkety+ with a more modern trusted local repository layout. -- Didier Roche Fri, 18 Nov 2016 12:08:37 +0100 ubuntu-make (16.11) zesty; urgency=medium [ Galileo Sartor ] * Removed jayatana dependency from android-studio * Change netbeans link * Support incorrect use of download_url when using GitHub API * Change superpowers repo [ Mehmet Keçeci ] * Update tr.po * Update ubuntu-make.pot [ Hannes De Valkeneer ] * Change netbeans checksum from md5 to sha256 [ Michael Chou ] * Android Studio duplicate icons in launcher fix [ Trent Schafer ] * Update post install message for all frameworks when needing to relogging [ Wilsen Hernandez ] * Spanish translation strings updated [ Didier Roche ] * Fix regression where Exec wasn't pointing at the correct install path when using a custom location * Decompress even slightly corrupted tar files. (latest golang release can now be uncompressed) * Prepare for zesty releases -- Didier Roche Fri, 18 Nov 2016 09:31:22 +0100 ubuntu-make (16.09) yakkety; urgency=medium [ Galileo Sartor ] * Add Sublime Text 3 support * Add Atom Support * Fix node_modules folder setting for respecting npmrc and add Node LTS * Fix eclipse download url * Change eclipse download-keyword to avoid conflicts * Fix firefox-dev install and exec * Fix unity 3D url * Adapt to new VSCode binary path [ Igor Vuk ] * Fix a few typos in README.md [ neopi21 ] * French translation update [ Jared Ravetch ] * Update Rust download url, add SSL cert for static.rust-lang.org, update tests [ Didier Roche ] * Have autopkgtest depend on libjs-jquery-throttle-debounce -- Didier Roche Thu, 22 Sep 2016 09:22:13 +0200 ubuntu-make (16.05) yakkety; urgency=medium [ Galileo Sartor ] * Fix Android-Studio and Android-SDK frameworks with newer website * Use github api for LightTable and superpowers frameworks * Add openjdk-8-jdk to android studio/sdk * Remove openjdk dependency for arduino [ Fabio Colella ] * Updated requirements for Netbeans to work on Xenial [ Jared Ravetch ] * Fix locale in tests [ Didier Roche ] * Done misc reviews on previous contributions * Change release hook to point to yakkety -- Didier Roche Wed, 04 May 2016 13:40:18 +0200 ubuntu-make (16.04) xenial; urgency=medium [ Galileo Sartor ] * Fix Xenial by adding an openjdk-8-jdk as a dependency to eclipse and intellij. (Fixes: #279) * Add language dependencies on IDEs specific to one language only (pycharm, rubymine…) [ Didier Roche ] * Write some future test strategy for pycharm/python medium tests -- Didier Roche Tue, 05 Apr 2016 09:24:55 +0200 ubuntu-make (16.03.2) xenial; urgency=medium * Fixup number for xenial -- Didier Roche Wed, 30 Mar 2016 09:15:03 +0200 ubuntu-make (16.03.1) xenial; urgency=medium * Fix test as python 3.5 downloader can return bigger size (on xenial) -- Didier Roche Wed, 30 Mar 2016 08:59:37 +0200 ubuntu-make (16.03) xenial; urgency=medium [ Galileo Sartor ] * Add Eclipse JEE support * Add Intellij EAP support * Fix Unity3D on lts mesa * Fix VSCode license page due to server changes * Fix Android-NDK due to server changes * Fix Clang support due to server changes * Fix Intellij .desktop file * Add a "or" package logic to the dependency check and install * Remove jayatana from intellij * Adapt large and medium tests to those changes [ Tankypon ] * Add Superpowers game editor framework [ Omer Sheikh ] * Add Kotlin compiler support * Remove openjdk from datagrip requirements [ Eakkapat Pattarathamrong ] * Add more test for Visual Studio Code [ Almeida ] * Update pt_BR translation [ Didier Roche ] * Change StartupWMClass to match the one Android Studio creates * Fix EULA acceptance translations in pt * Add more tests on symlinks creation and removal * Fix and make more reliable test infrastructure + some cleanup logic * Adapt large and medium tests to those changes -- Didier Roche Wed, 30 Mar 2016 08:22:24 +0200 ubuntu-make (16.02.1) xenial; urgency=medium [ Galileo Sartor ] [ Didier Roche ] * Fix Visual Studio Code to use permanent links as the website changed. Adapt tests to it. -- Didier Roche Wed, 10 Feb 2016 09:43:20 +0100 ubuntu-make (16.02) xenial; urgency=medium [ Galileo Sartor ] * Add Nodejs support with always latest node and npm now available! * Add Lighttable IDE support. * Create symlinks in a bin/ directory which is now added to user's PATH for each .desktop file created. That way, people can run their app from the command line as well. * All of those covered by small medium and large tests. [ Patricio Pérez ] * Add Spring Tools Suite and its testsuite. [ Omer Sheikh ] * Add JetBrains Datagrip with tests * Add python-gnupg to requirements.txt. [ Didier Roche ] * Disable Visual Studio Code installation for now. Adapt tests for that change. -- Didier Roche Tue, 09 Feb 2016 08:47:49 +0100 ubuntu-make (16.01.2) xenial; urgency=medium [ Galileo Sartor ] * Add swift lang support with according tests. * Add support for Eclipse php with tests. * Add support for Eclipse cpp with tests. [ Evan McIntire ] * dd manpage that is generated from the --help text. [ Didier Roche ] * Fix, and implements some testing for Swift, Eclipse php and cpp. * Add gpg key support so that we can mock and add it to frameworks, working around some uid != euid limitations. * Compile local python file under current user name in tests. -- Didier Roche Wed, 20 Jan 2016 17:38:39 -0800 ubuntu-make (16.01.1) xenial; urgency=medium * Fix Go support as of 1.5.3, they now publishes a sha256 instead of a sha1 checksum. * Adapt tests to it. * A lot of work on tests: - add local/vm/remote args to runtests to easily run tests in locally, in an adt environment or remotely on the official infrastructure. - minimizing autopkgtests installation - docker fixes with proxy for medium tests - ensure we run with a dummy xorg driver - ensure compiz is running before running large and custom tests - fix TESTS=all triggering custom tests - fix not installing ubuntu-make package itself for git tests -- Didier Roche Thu, 14 Jan 2016 12:26:52 +0100 ubuntu-make (16.01) xenial; urgency=medium [ Galileo Sartor ] * Always deliver the latest Unity3D version (beta) to our users. * Ensure we always download latest available eclipse java IDE version. This enables users to now get eclipse Mars from Ubuntu Make! [ Didier Roche ] * Enable setting up Firefox Dev as default browser. * Move Visual Studio Code to IDE category. Keep it still on the web category for backward compatiblity. Adapts tests to ensure both category works (with a warning on the web one). * Move the testing infrastructure from jenkins to ubuntu autopkgtests: - create pep8/small/medium/large/all targets to mimic runautopkgtests behavior. - add a setup test bed, installing an ubuntu-desktop image, grabbing git branch or system package and generating stats info. - add another collecting coverage test to generate and copy stats to artefacts directory. - a custom target is triggered when one or more specific tests are desired like --env="TESTS=tests/small/.py tests.small.foo:TestClass:test_bar". - all those tests are handled by a TESTS env variable. If not set, we run pep8 and small tests. - creating utils and scripts to factorize most of the logic. * Protect against invalid tar archive that can be opened but not fully extracted. * Remove libxp6 dep from Stencyl as optional and not available from wily. * Install test dependencies from package and autopkgtests list. Use that logic in both autopkgtest infra and jenkins. * Make test_install_progress more robust as apt 1.1.5 changed its update signaling behavior. * Add in baseinstaller some way to only match last link when parsing. * Rework foreign architecture addition and detection to ensure we only call it once (we were calling them once per package previously), fix some races in cache handling. Move this facility to tools and restructure tests for this, while adding some more. * Add locks to avoid a race condition when creating temp file (to not create them as root) and add a new contextwrapper for as_root() with its tests. * Drop sshpass in favor of ssh key for docker image connection. * Some misc fixes: - Change some error messages and making them localizable. - fix an issue to avoid nested fakeroot calls. - Ensure we always kill children process and not the wrapper in container. - Add a fallback when os.getlogin() returns transient errors. - Normalize end of line tests comparaison. - Fix some possible failure when issuing a progressbar update. - Restructure, decouple and grab additional mocks for tests - Restore properly the initial environment in test_settings to avoid env leaks bugs. - Import cleanups. -- Didier Roche Tue, 12 Jan 2016 09:39:08 +0100 ubuntu-make (15.12.1) xenial; urgency=medium [ Eldar Khayrullin ] * Update Unity3D link to latest [ Didier Roche ] * Fix rust for their latest release as they changed rustlib directory * Adapt rust medium assets * Fix medium tests by changing unity server host * Some tidy up on BeautifulSoup latest release -- Didier Roche Thu, 17 Dec 2015 07:36:45 +0100 ubuntu-make (15.12) xenial; urgency=medium * Fix JetBrain's based IDE due to their new website deployement: - Use now their API directly. - Adapt medium tests and assets to follow that new structure. * Add a deprecation warning on udtc command (will be removed after 16.04 LTS) -- Didier Roche Fri, 11 Dec 2015 10:52:53 +0100 ubuntu-make (15.11.2) xenial; urgency=medium [ Abigail Buccaneer ] * Add JetBrains CLion C/C++ IDE support. [ Eldar Khayrullin ] * Complete Russian translation. [ Translation team ] * Refresh po files with latest community translations. Thanks to all our translator community! [ Didier Roche ] * Add Twine game editor support. * Ensure --help always show category help when following category, even if it has default frameworks. * Add tests (small/medium/large) to cover those. * Add ZSH completion to the same level as bash completion. * Fix visual studio icon which changed its path (detected thanks to our testsuite). * Add medium and large tests for CLion. * Fallback to plain english if language support isn't fully installed. * Fix incorrect pt_BR translations. * Add better description for jetbrain IDEs. * Create and move a bunch of Android tests to a mock BaseInstaller based one. This enables us to cut large test time by a magnitude of 2. Using that opportunity to add more tests and complete existing ones. * Standardize language test bed to run in plain english whatever your configuration is. * Misc. tests enhancements and tools fixes. * Move build dependencies only needed for tests to another ppa (ppa:ubuntu-desktop/ubuntu-make-builddeps) and add it in jenkins tests. This way, people using Ubuntu Make on older release are not impacted by the need of newer version of tests frameworks like pexpect and won't install them. Hook that ppa in Travis CI, our jenkins infra and refresh contributor intro to ask adding that ppa for testing. * Enhance our jenkins job for testing a pull request branch and other minor test job enhancements. * Update French translations. * Update translation template for new and updated frameworks. -- Didier Roche Tue, 24 Nov 2015 08:06:03 +0100 ubuntu-make (15.11.1) xenial; urgency=medium [ Fabio Colella ] * Added support for Netbeans IDE, with possibility of extension to support its flavours. * Add large and initial support for medium tests. [ Jared Ravetch ] * Add Rust support, installing the latest rust compiler and tools version. * Initial support for medium and large tests. * Override GOROOT value instead of appending it (Go doesn't support GOROOT having multiple values). [ Eldar Khayrullin ] * Update unity3d version up to 5.1.0f3+2015091501. [ Sebastian Schuberth ] * Change android NDK env variable to use NDK_ROOT instead of ANDROID_NDK. [ Didier Roche ] * Fix webstorm icon renamed upstream. * Ship version file as part of the install (Now --version really works on packaged flavor as well) + stamp generated binary with correct version. * Fix BaseInstaller to not crash when all downloads assets are 404 + add medium tests for this. * Ensure -r global option behave like --remove. * Some style, refactoring and formatting tidy up for recent merges and changes. * Add medium assets, certificates and additional failure test cases for netbeans and rust. * Update docker container for medium tests with new certificates. * Readd Travis CI integration running pep8 and small tests (with badge status and updated wording in README). New pushes and pull requests are now automatically tested on those 2 kinds of tests. * Fix and updates dependencies for package and pip virtualenv deps. * Standardize the test environment so that people running tests using for instance zsh are not impacted. * Finish up shipping static files support for future frameworks. * Using scala framework for loading tests and making autopkgtests pass on armel64 (android not available on this arch). * Improve releasing script and migrate gbp config to new headers. [ Translators ] * Refreshed translation template and updated translations. Thanks to all our translators! - new supported languages: fa, pt_BR - Updating the following languages: de, en_AU, en_CA, en_GB, eu, hr, it, pl, ru, te, zh_CN, zh_HK -- Didier Roche Tue, 10 Nov 2015 09:12:26 +0100 ubuntu-make (15.11) xenial; urgency=medium [ Omer Sheikh ] * Change default install path to ~/.local/share/umake/, depending on $XDG_DATA_HOME. * Add tests for those. * Improve tests stability in different environment (particularly jenkins) by creating wrapper around pexpect.spawnu. The wrapper sets the virtual terminal dimensions before calling pexpect.spawnu. This is to solve the problem of newline and carriage returns appearing in the stdout of created processes when testing under jenkins. [ Sebastian Schuberth ] * Fix changelog name. * Set the ANDROID_HOME and NDK_ROOT environment variables for android NDK frameworks. [ Jared Ravetch ] * Fix user message when prompting user to restart shell session. [ Didier Roche ] * Add a --version option to print current ubuntu make version. The rules are: - if the user is on a released version, then print this version - if the user is on a git branch, use: - version-#commits-shortsha1 if there is no local or staged changes - version-#commits-shortsha1-dirty if there is some locals or staged changes - finally, if the user is a local checkout, but without git history, just print: version+unknown * Fix --remove when used before a category name. Now, you can properly umake --remove and the framework will be removed. * Fix framework env variables not removed for zsh shells on --remove. * Fix cmd list mangling for large Android NDK tests. * Add some autoreleasing script, to bump version, add them to stage, tag and commit. * Enable multiple decompressions to end up in same directory and adapt frameworks to this new framework API. * Adjust DownloadCenter number of threads to match number of assets to download. * Make BaseInstaller supporting multiple assets downloads and fix it to only reflect download progress when we have all download size data. We could have one download finishing up (and so global being at 100%) while other downloads didn't start yet. Ensure we have all assets size before reporting first download global progress. * Fix as well cleaned path to not be removed. * Filter in BaseInstaller to not decompress assets that are files to copy. * Add a bunch of small, medium and large tests for versioning, removal, env variable cleanups, parallel decompressions in the same directory, done callback counts for decompression and downloads. * Add a way to specify multiple ports (and hosts) in medium tests. This will be used in future frameworks which rely both on https and http downloads. Test tools can now expose multiple ports inside the container. Changed as well all medium tests to adapt to this new API. * Ensure we source .profile when executing command in container. * Various changes to run medium tests even on system installed version. * Save new jenkins jobs enabling medium tests and add branch-targeted jenkins job to test branches not merged yet into master. * Better medium tests stability support and optimization. * Package new version of pexpect and add dependency markers. * Some PR post-merge fixes and various refactoring. * Remove WIP marker in README. -- Didier Roche Tue, 03 Nov 2015 10:39:04 +0100 ubuntu-make (15.10) wily; urgency=medium * Fix Dartlang download due to its new website layout. * Fix pycharm educational link as their linux download returned some windows binary. * Adapt medium tests assets to those new website layouts and new certificates. * Add support for frameworks to poke for download on multiple hosts (needed for the Dartlang case). * Add support for medium tests to have a SNI server to cope with requests on multiple hosts when faking server inside the container, including delivering the correct content and certificate. * Ensure that probing for reinstall in frameworks is only requiring the right engagement level from the user (and add tests for this). * Add some generic frameworks functionality for detecting intallation state, enabling to remove a lot of similar code in all frameworks. * Handle properly directory which doesn't exists in archive to decompress. * Ensure that a logging config selection via conffile display the selected logging level. * Enhance logging and debugging support. * Add a bunch of new tests and raised the test coverage to reach 93%. * Add missing requirements from contributor documentation. Big thanks to aung for this! * Make CI jenkins jobs being more resilient to random failures (distro, network…). * Test jenkins jobs are now archived. * Misc code cleanups and dead code removal. -- Didier Roche Thu, 08 Oct 2015 10:19:14 +0200 ubuntu-make (15.09.2) wily; urgency=medium * Ignore continuation line having to be a multiple of 4 in older pep8 release (making identation not aligned with above line). * This then trigger new warnings for double spaces, fix them. -- Didier Roche Thu, 10 Sep 2015 08:00:33 +0200 ubuntu-make (15.09.1) wily; urgency=medium * Add support for installing android SDK only by Sebastian Schuberth - add associated set of medium and large tests. * Rationalize exit status of umake by Omer Sheikh - every error now, in addition to print some errors, exits as expect with an exit code of 1. - add and modify large tests, to ensure that each framework (those using BaseInstaller and those having some dedicated code path) are behaving the same for errors. - mock in medium tests bad page download to exercise the error code path here as well. * Fix some pep8 issues (trusty only), some small tests broken by previous merges. -- Didier Roche Thu, 10 Sep 2015 07:24:23 +0200 ubuntu-make (15.09) wily; urgency=medium * Unity 3D editor experimental support. You can install it through: umake games unity3d. Only amd64 is currently supported upstream. * Fix Arduino download as upstream web pages changes. Support more release version format and ensure we don't raise an exception but only log an error. * Add license support to Android NDK. * Adapt and add large and medium tests for both Unity 3D and Android NDK. * Various enhancements to enable decompressing shell-embedded archives without copying entire files. Add corresponding tests. * Refactor Android license parsing to be reusable to future Android SDK support. * Fix a bug where if license was after the download links, we wouldn't find the license. * Better add_to_user_env API for contributors. * Minor cosmetic and small bug fixes. -- Didier Roche Tue, 01 Sep 2015 10:51:32 +0200 ubuntu-make (15.08) wily; urgency=medium * Add scala support and add related medium and large tests. (Igor Vuk) * Fix Visual Studio Code download URL as VSCode updated their download mechanism on their website. (Vartan Simonian) * Fix progress bar out of range exception. (Anton Antonov) * Change medium VSC assets to match new download page. * Do some pep8 fixes triggered by new pep8 version. -- Didier Roche Thu, 13 Aug 2015 07:43:12 +0200 ubuntu-make (0.9.2) wily; urgency=medium * Enable language selection in firefox developer tools (thanks to Omer Sheikh): - Now the installation of firefox developer tools enable to choose interactively one of the available language (default being US). - add a --lang= parameter to switch to another language in non interactive mode. - additional tests and mocks for the new options and capability * Prevent double error logging when a TextWithChoice doesn't get the correct user's input. Adapt tests to it. * Fix a double empty [] when no shortcut is present. * Updated README to improve readability. Moved to more passive language. (thanks Brian P. Sizemore) -- Didier Roche Tue, 04 Aug 2015 09:06:57 +0200 ubuntu-make (0.9.1) wily; urgency=medium * Change test to prevent FTBFS with 3.5: assert_has_calls() * Print whole process output before getting the pexpect exception to get more info when a medium or large test is failing -- Didier Roche Fri, 24 Jul 2015 11:59:57 +0200 ubuntu-make (0.9.0) wily; urgency=medium * Force depending only on default python3 for the current ubuntu version. -- Didier Roche Tue, 21 Jul 2015 10:21:29 +0200 ubuntu-make (0.9) wily; urgency=medium * New arduino support. Thanks to Tin Tvrtković to have provided most of the work. * Fix parsing for Visual Studio Code 32 bits as upstream page changed. * Deprecate Dart Editor framework (marked for remove only) and add Dart SDK new framework as per Dart 1.11, the Editor is not supported anymore. * Added or adapt tests for those new cases. * Refresh and add helpers to large and medium tests to factorize them much more and aligning information we check from the .desktop files (exec and icon paths). * Remove tests data from umake runtime. * Some test cleanups and mock refresh (android studio, Visual Studio Code, Android NDK). -- Didier Roche Tue, 21 Jul 2015 09:34:45 +0200 ubuntu-make (0.8.2) wily; urgency=medium * Fix Visual Studio Code support due to new upstream archive layout and web page content. * Add support for 32 bits installation of VSC as now supported upstream. * Refresh and adapt large and medium tests to reflect those changes. -- Didier Roche Wed, 10 Jun 2015 09:41:49 +0200 ubuntu-make (0.8.1) wily; urgency=medium * Match Android NDK with new download URL. * Adapt medium test accordingly. * Fix one failing Android large test. -- Didier Roche Mon, 08 Jun 2015 08:59:30 +0200 ubuntu-make (0.8) wily; urgency=medium * Fix icon name that changed in Android Studio 1.2. Thanks Mark Trolley for this contribution! * Add tests to ensure that we are checking icon file name for android frameworks as well. * Rewrite the access in tests for icons and executables to read directly from the optional installed desktop file. Keep a way to override it for frameworks without desktop file. * Ensure we can remove deprecated frameworks. They only appear in shell completion and --help only if you had them installed. Prevent any reinstallation but only get a removal option. * Addition of a full non interactive installation mode. * Add tests for all those new features and fix some previous failing tests. -- Didier Roche Thu, 07 May 2015 11:13:09 +0200 ubuntu-make (0.7) vivid; urgency=medium * Add Visual Studio Code support (under the "web" category) * Fix an error message printing for the eclipse framework if the server doesn't return a success code -- Didier Roche Thu, 30 Apr 2015 13:06:50 +0200 ubuntu-make (0.6.2) vivid; urgency=medium * New translations: - Greek, Indonesian * Updated translations: - German, Spanish, French -- Didier Roche Thu, 02 Apr 2015 09:56:30 +0200 ubuntu-make (0.6.1) vivid; urgency=medium * Set dart-editor as the command to install the editor and adapt the tests to this * Fix some strings not marked for translations * Print help for category with no default framework * Fix get binary depends with empty starting line in debian/control * Add missing tests deps in debian/tests/control -- Didier Roche Thu, 12 Mar 2015 08:14:02 +0100 ubuntu-make (0.6) vivid; urgency=medium * New IDEs support and various cleanups by Anton Antonov: - rubymine - pycharm educational - pycharm professional - webstorm - phpstorm * All of those covered by medium and large tests * Add zsh support + tests (thanks Anton Antonov again) * Various small code enhancements -- Didier Roche Wed, 18 Feb 2015 09:47:08 +0100 ubuntu-make (0.5) vivid; urgency=medium * Add Idea Ultimate support, thanks to Tin Tvrtković. * Add Android NDK support. * Add Dartlang support. * Add Firefox Developer Edition support. * Get new ftp download support as Intellij downloads can redirect to ftp download based on location. Thank to Tin Tvrtković. * Refresh de and es translations. Thanks to all contributors! * Rationalize what is up for translations and refresh i18n templates for new strings. * Fix some is_installed() detection. * Workaround a glib issue when some Unity launcher icon doesn't appear. * Some tests enhancements, cleanups and fixes. -- Didier Roche Thu, 12 Feb 2015 10:48:20 +0100 ubuntu-make (0.4.1) vivid; urgency=medium * Fix for Intellij IDEA download page, thanks to Tin Tvrtković. * Add jayatana dependency for ides based on intellij so that even older releases than vivid get appmenu support. * Some misc test and docker container fixes. -- Didier Roche Thu, 22 Jan 2015 09:00:45 +0100 ubuntu-make (0.4) vivid; urgency=medium * Add go support from the golang google compiler * Add a game category with stencyl support * Refactor and add some tests for those -- Didier Roche Tue, 06 Jan 2015 10:49:58 +0100 ubuntu-make (0.3) vivid; urgency=medium * New release featuring intellij IDEA and Pycharm support (from jetbrain) in their community edition. Thanks to Tin Tvrtković for this work. They both are covered by new tests. * Add dependency on beautifulsoup for easier html parsing by Tin Tvrtković. * Ensure we download Android Studio over https. * Miscellaneous medium tests fixes. -- Didier Roche Tue, 16 Dec 2014 09:33:21 +0100 ubuntu-make (0.2) vivid; urgency=medium * Releasing under new name: ubuntu-make. Handle transition by shipping a temporary binary under the older name (udtc). New command is umake. Note as well that the new framework environment variable is UMAKE_FRAMEWORKS. * Provide compatibility binary (udtc) for now in the transitional package. Also move previous configuration file location to the new one. * Update Standards-Version * Fix Android Studio installation, now that it reached 1.0 milestone. * Removing Android Eclipse (adt) from Ubuntu Make: upstream doesn't provide any bundle anymore as this tools is deprecated in favor of Android Studio. -- Didier Roche Tue, 09 Dec 2014 08:23:33 +0100 ubuntu-developer-tools-center (0.1.1-0ubuntu1) vivid; urgency=medium * Bug-fix release as Google changed their android-studio checksum from md5sum to sha1sum. Implementing sha1sum largely thanks to Tin Tvrtković work! * Adapt tests + new tests for sha1sum. * Note that the new Android Studio doesn't ship the sdk with it anymore. You need to download it manually and set the path to it. Will try to get in touch with the android studio developer team for this. -- Didier Roche Tue, 04 Nov 2014 09:55:41 +0100 ubuntu-developer-tools-center (0.1-0ubuntu1) vivid; urgency=medium * Add eclipse support as a standalone IDE. Usage is: udtc ide eclipse. Thanks to Tin Tvrtković for his excellent work and tests implementation. * Add android adt support (through eclipse). Usage is: udtc android eclipse-adt. Added tests for it as well * adb and other android tools are now added to user path while installing an android framework * Support removal of framework. If you installed a framework and want to remove it, just use: udtc android android-studio --remove * Numerous typo fixes thanks to Igor Vuk * Enable loading of local framework. They are controlled by UDTC_FRAMEWORKS env variable which can point to any path containing local frameworks * Support reinstallation in different folder than the origin one, cleaning the original directory. * DownloadCenter now support redirections. Thanks Tin Tvrtković for this work * Add support for decompressing zip files in Decompressor * New and refresh translations: de, en_AU, en_CA, en_GB, es, eu, fr, hr, it, pl, ru, te, zh_CN, zh_HK. Thanks to all translators for their hard work! * Improve i18n support * Protect against mistyping with multiple frameworks * Framework support refactoring to avoid code duplication * Tests fixes and refactoring for better scalability * Fix logging support during test runs * Reshape docker files to have fewer layers * Don't raise any Exception for unexpected CLI args -- Didier Roche Wed, 29 Oct 2014 10:21:01 +0100 ubuntu-developer-tools-center (0.0.5) utopic; urgency=medium * Addition for the test jenkins server: - Add helper to display binary depends - Output xml tests and coverage report - Add xunit artefacts support in runtests * Some tests enhancement for working in the daily jenkins environment: - Change installing in conflict package prediction. - Give some time for the container in medium tests to start - Remove full install timeout logic. Instead, have a timeout if there is no new stdout/progress report change for a while. This ensure less flakyness in case of really slow network. - Remove on output testing first INFO message detection as it's a false positive. * No output by default when running tests: - Coverage tests doesn't print any stdout or logging info unless a tests is failing. - Debug profile is using the debug logging configuraiton as well. - Don't rely on importing tests/__init__.py to define logging format for nose. - Ensure subprocess (medium/large tests) set the same logging level as well. - Add a stdout hanlder in subprocess as well while testing (using the correct profile and be able to detect warning/errors) * debian/rules: - no need for --no-config for running tests anymore * Misc cleanups: - some refactoring of runtests - remove unusued imports - removed unused profile options - update documentation for the new logging profiles change. * Have pep8 tests passing on system version as well. * Add Spanish, Basque and Chinese (Hong Kong) translations. Thanks to all translators! -- Didier Roche Tue, 09 Sep 2014 16:48:12 +0200 ubuntu-developer-tools-center (0.0.4.1) utopic; urgency=medium * GSettings:schema has been deprecated and glib shows a warning about it. Fix the deprecation by switching to schema-id which is supported in 14.04. -- Didier Roche Mon, 01 Sep 2014 17:14:06 +0200 ubuntu-developer-tools-center (0.0.4) utopic; urgency=medium * Enhance some tests by adding more info in case of failure and decouple some concerns. * Fix medium tests in using server name back as sbuild supports it again. * Refreshed certificates which expired and document how to get longer ones. * First trial to get medium tests running as autopkgtests, but disabled for now (Docker permission error inside the autopkg chroot) * Refactor i18n support with dropping babel and automatically run the commands when setuptools is building. * Add fr and zh_CN translations. -- Didier Roche Thu, 28 Aug 2014 11:03:09 +0200 ubuntu-developer-tools-center (0.0.3) utopic; urgency=medium * Fix coverage reports by importing tested modules only when needed and when overriding "packages" and "__files__", by reloading the module * Some cleanups (removed unused imports) * Add allow-stderr for adt tests: as nose-cov print some debug output at start which makes adt failing then. As we control, stderr and warnings during tests, disable this check. -- Didier Roche Thu, 28 Aug 2014 08:12:31 +0200 ubuntu-developer-tools-center (0.0.2.2) utopic; urgency=medium * debian/control: - add XS-Testsuite as some uploads may happen from trusty -- Didier Roche Wed, 27 Aug 2014 15:24:18 +0200 ubuntu-developer-tools-center (0.0.2.1) utopic; urgency=medium * Rebuild to run autopkgtests * Fix some pep8 issues on utopic and enable them during package build -- Didier Roche Wed, 27 Aug 2014 15:00:29 +0200 ubuntu-developer-tools-center (0.0.2) utopic; urgency=medium * Adapt one test as we disabled the android eclipse framework (not ready yet) -- Didier Roche Mon, 11 Aug 2014 17:44:12 +0200 ubuntu-developer-tools-center (0.0.1) utopic; urgency=medium * Initial release, supporting android-studio -- Didier Roche Fri, 01 Aug 2014 09:37:20 +0200 ubuntu-make-16.11.1ubuntu1/debian/gbp.conf0000664000000000000000000000010613013560574015174 0ustar [buildpackage] export-dir=../build-area/ export=INDEX ignore-new=True ubuntu-make-16.11.1ubuntu1/debian/ubuntu-developer-tools-center.postinst0000664000000000000000000000032713013560574023310 0ustar #!/bin/sh set -e case "$1" in configure) rm -f /etc/bash_completion.d/udtc ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 ubuntu-make-16.11.1ubuntu1/debian/control0000664000000000000000000000346513013560574015173 0ustar Source: ubuntu-make Section: devel Priority: optional Build-Depends: debhelper (>= 9), dh-python, gettext, python3, python3-apt, python3-argcomplete, python3-bs4, python3-gi, python3-gnupg, python3-setuptools, python3-nose, python3-nose-cov, python3-nose-json, python3-pep8, python3-pexpect, python3-progressbar, python3-yaml, python3-requests, python3-xdg, dbus-x11, fakeroot, help2man, Maintainer: Didier Roche Standards-Version: 3.9.6 X-Python3-Version: >= 3.4 XS-Testsuite: autopkgtest Package: ubuntu-make Architecture: all Depends: ${misc:Depends}, ${python3:Depends}, python3-apt, python3-argcomplete, python3-bs4, python3-gi, python3-gnupg, python3-progressbar, python3-yaml, python3-requests, python3-xdg, Description: setup your development environment on ubuntu easily Ubuntu Make provides a set of functionality to setup, maintain and personalize your developer environment easily. It will handle all dependencies, even those which aren't in Ubuntu itself, and install latest versions of the desired and recommended tools. . For now, you can configure a complete android studio environment. Package: ubuntu-developer-tools-center Architecture: all Section: oldlibs Priority: extra Depends: ubuntu-make, ${misc:Depends}, ${python3:Depends} Description: transitional dummy package This is a transitional dummy package only providing previous udtc binary instead of umake. It can safely be removed. ubuntu-make-16.11.1ubuntu1/debian/ubuntu-make.install0000664000000000000000000000010413013560574017400 0ustar usr/share/zsh/vendor-completions/ usr/bin/umake usr/lib/ usr/share/ ubuntu-make-16.11.1ubuntu1/debian/rules0000775000000000000000000000056513013560574014646 0ustar #!/usr/bin/make -f #DH_VERBOSE=1 %: dh $@ --with python3 --buildsystem=pybuild --fail-missing override_dh_auto_test: ./runtests pep8 small override_dh_installman: help2man -n "Deploy and setup developers environment easily on ubuntu" -o debian/umake.1 bin/umake sed -i s/+unknown//g debian/umake.1 dh_installman override_dh_clean: rm -f debian/umake.1 dh_clean ubuntu-make-16.11.1ubuntu1/debian/ubuntu-developer-tools-center.install0000664000000000000000000000001513013560574023065 0ustar usr/bin/udtc ubuntu-make-16.11.1ubuntu1/debian/compat0000664000000000000000000000000213013560574014756 0ustar 9 ubuntu-make-16.11.1ubuntu1/debian/tests/0000775000000000000000000000000013013560574014722 5ustar ubuntu-make-16.11.1ubuntu1/debian/tests/collect-coverage0000664000000000000000000000061313013560574020063 0ustar #!/bin/bash # collect and generate global coverage report # Author: Didier Roche set -e . `dirname $0`/utils # combine the reports cd $coverage_dir python3-coverage combine python3-coverage html -d html-coverage python3-coverage xml # archive the results cp .coverage ${ADT_ARTIFACTS} cp -a *coverage* ${ADT_ARTIFACTS} # print on stdout as well python3-coverage report ubuntu-make-16.11.1ubuntu1/debian/tests/large0000664000000000000000000000032213013560574015734 0ustar #!/bin/bash # Author: Didier Roche set -e . `dirname $0`/utils # skip tests if not requested skip_if_no_in_list # require compiz to run wait_for_compiz run_tests large publish_results ubuntu-make-16.11.1ubuntu1/debian/tests/control0000664000000000000000000000102613013560574016324 0ustar # Setup an ubuntu-desktop install which can logout and login Tests: setup-testbed, pep8, small, medium, large, custom, collect-coverage, Depends: @builddeps@, ubuntu-desktop, git, docker.io, sloccount, libjs-jquery, libjs-jquery-hotkeys, libjs-jquery-isonscreen, libjs-jquery-tablesorter, libjs-jquery-throttle-debounce, Restrictions: rw-build-tree, isolation-machine, allow-stderr, ubuntu-make-16.11.1ubuntu1/debian/tests/setup-testbed0000664000000000000000000000644713013560574017450 0ustar #!/bin/bash # setup an ubuntu-desktop machine with autologin and dependencies # Author: Didier Roche set -e . `dirname $0`/utils if [ -n "$ADT_REBOOT_MARK" ]; then exit 0 fi export DEBIAN_FRONTEND=noninteractive # configure docker sudo -n addgroup $(whoami) docker # the config file isn't a pam file (shouldn't have export) when used from the # service file under systemd if [ -d /run/systemd/system/ ]; then grep proxy /etc/environment | sudo -n tee -a /etc/default/docker else # this is sourced for sysv init scripts sed -n '/proxy/ { s/^/export /; p}' /etc/environment | sudo -n tee -a /etc/default/docker fi # ensure we have a cgroup controller installed (systemd for wily and on, cgroup-lite for trusty) if ! `dpkg -l systemd-sysv 1>/dev/null 2>&1`; then sudo -n apt --no-install-recommends install -y cgroup-lite fi # workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=808203 sudo -n rm -f /etc/dpkg/dpkg.cfg.d/pkg-config-hook-config # enable xserver dummy driver sudo -n apt --no-install-recommends install -y xserver-xorg-video-dummy cat <> ~/.ssh/authorized_keys # install ubuntu-make if we are running system tests, otherwise install only deps from debian/control if [ "$(is_package_test)" = "true" ]; then PACKAGES="ubuntu-make" else PACKAGES=$(tests/daily_runs/get_binary_depends ubuntu-make) fi sudo -n -E apt install -y $PACKAGES # store ubuntu make version and packages config_dir="$ADT_ARTIFACTS/config" mkdir -p $config_dir # discover target: package/branch, origin if [ "$(is_package_test)" = "true" ]; then # clean the source package to ensure we don't have duplicated files after # build for sloccount debian/rules clean type="system" origin="$(apt-cache policy ubuntu-make | sed -n '/\*\*\*/ {n;p}' | cut -d' ' -f 10)" [ -z "$origin" ] && origin="Local package" version="$(umake --version)'" else type="branch" upstream_short="$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))" IFS=/ read repo branch <<< $upstream_short repo_url=$(git config --get remote.${repo}.url) origin="${repo_url} $branch" version="$(bin/umake --version)'" fi cat << EOF | tee "$config_dir/version" { 'target': { 'type': '$type', 'origin': '$origin', 'version': '$version', }, 'date': { 'timestamp': '$(date +%s)', 'utc': '$(date -u)' }, 'arch': '$(arch)' } EOF dpkg -l > "$config_dir/packages_list" echo -e "\nStats:" sloccount * | head -n -17 | tail -17 | tee "$config_dir/stats" # remove umake directory for coverage reporting on real used files if [ "$type" = "system" ]; then rm -r umake/ fi # compile local python file under current user to avoid some root-owned compile # file like for local server python3 -m compileall . sudo -n /tmp/autopkgtest-reboot ready ubuntu-make-16.11.1ubuntu1/debian/tests/pep80000664000000000000000000000025013013560574015516 0ustar #!/bin/bash # Author: Didier Roche set -e . `dirname $0`/utils # skip tests if not requested skip_if_no_in_list run_tests pep8 publish_results ubuntu-make-16.11.1ubuntu1/debian/tests/medium0000664000000000000000000000025213013560574016124 0ustar #!/bin/bash # Author: Didier Roche set -e . `dirname $0`/utils # skip tests if not requested skip_if_no_in_list run_tests medium publish_results ubuntu-make-16.11.1ubuntu1/debian/tests/small0000664000000000000000000000025213013560574015754 0ustar #!/bin/bash # Author: Didier Roche set -e . `dirname $0`/utils # skip tests if not requested. skip_if_no_in_list run_tests small publish_results ubuntu-make-16.11.1ubuntu1/debian/tests/utils0000664000000000000000000000562313013560574016013 0ustar #!/bin/bash # Author: Didier Roche coverage_dir=/tmp/global-coverage # publish test results for given test run. Keep a secondary coverage copy (as the first one is cleaned) for collect step function publish_results { test_type=$(basename $0) output_dir="$ADT_ARTIFACTS/$test_type" mkdir -p $output_dir mv nosetests.* ${output_dir} mv .coverage ${output_dir} mv *coverage* ${output_dir} mv *.log ${output_dir} mkdir -p $coverage_dir cp ${output_dir}/.coverage ${coverage_dir}/.coverage.${test_type} } # this function need to be run in ubuntu make directory" function is_package_test { if [ -d ".git" ]; then echo "false" return fi echo "true" } # add --system if we run from a package dir function add_runtests_opts { if [ "$(is_package_test)" = true ]; then echo "--system" return fi } # skip current test if not "all" or in the list of $TESTS # if the test variable is empty, we still want to run some tests as per of package testing function skip_if_no_in_list { # tests to run if nothing was provided [ -z "$TESTS" ] && TESTS="small" test_type=$(basename $0) re=\\btests[\./] # we are in the custom type test flavor if [[ "$test_type" = "custom" ]]; then if [[ "$TESTS" =~ $re ]]; then return else echo "No specific mentioned in \$TESTS; skipping test" exit 0 fi fi # if we run only some tests of the current type, (tests..), disable all and this category if [[ "$TESTS" =~ $re ]]; then echo "Specific tests required, skipping general ones." exit 0 fi retype=\\b${test_type}\\b reall=\\ball\\b if [[ "$TESTS" =~ $retype ]] || [[ "$TESTS" =~ $reall ]]; then return fi echo "$test_type isn't mentioned in \$TESTS; skipping test" exit 0 } # we need to run in a ssh subshell to get a real terminal connexion so that ssh can returns when subprocess are killed function run_tests { ssh -o StrictHostKeyChecking=no -t -t 127.0.0.1 "cd $PWD; DISPLAY=:0 dbus-launch ./runtests --publish --coverage $(add_runtests_opts) $@" } # wait for compiz to start, exit 1 after a timeout if not running. function wait_for_compiz { timeout=100 while [ ! `pgrep -c compiz` -gt 0 ]; do if [ $timeout -le 0 ]; then echo "compiz didn't start" echo "------------- /var/log/lightdm/x-0.log -------------" sudo -n cat /var/log/lightdm/x-0.log || true echo "------------- /var/log/lightdm/.lightdm.log -------------" sudo -n cat /var/log/lightdm/lightdm.log || true echo "------------- ~/.xsession-errors -------------" cat ~/.xsession-errors || true exit 1 fi timeout=$((timeout - 5)) sleep 5 echo "waiting for compiz to start... (${timeout}s left)" done } ubuntu-make-16.11.1ubuntu1/debian/tests/custom0000664000000000000000000000036113013560574016157 0ustar #!/bin/bash # Author: Didier Roche set -e . `dirname $0`/utils # skip tests if not requested skip_if_no_in_list # require compiz to run as we might right large tests wait_for_compiz run_tests $TESTS publish_results ubuntu-make-16.11.1ubuntu1/TODO0000664000000000000000000000004413013560574013024 0ustar - shell complete tests in runtests