Carton-v1.0.28/000755 000765 000024 00000000000 12720763413 014165 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/Changes000644 000765 000024 00000024672 12720763413 015473 0ustar00miyagawastaff000000 000000 Revision history for carton v1.0.28 2016-05-23 22:30:48 PDT - Emit the line when parser error happened v1.0.27 2016-05-23 12:34:58 PDT - revert v1.0.25 undef special casing v1.0.26 2016-05-21 20:29:11 PDT - Make sure 'undef' and '0' are encoded properly writing 02packages as well v1.0.25 2016-05-21 20:21:22 PDT - Handle 'undef' in snapshot and 02packages, separate from '0' v1.0.24 2016-05-08 11:56:14 PDT - Same as v1.0.23, repackaging v1.0.23 2016-05-08 11:50:00 PDT - Update FAQ to use with perlbrew #202 - Update github URL - Fix regular expression warnings in perl 5.22 #204 v1.0.22 2015-08-11 22:17:44 PDT - Fixed a bug where carton update gives an error when there's nothing to update - Update a link to point to the new IRC chatroom #cpanm on irc.perl.org v1.0.21 2015-05-15 12:21:47 PDT - Changed Module::Reader dependency to requires for now, since it will be required on the runtime by the fatpacked carton. v1.0.20 2015-05-08 16:20:37 PDT - INCOMPATIBLE: Disable fatpack generation in carton bundle by default. Use the new standalone command carton fatpack, to generate vendor/bin/carton v1.0.19 2015-05-01 17:48:06 PDT - Remove Module::Build and MakeMaker from prerequisite since cpanm will install them as required v1.0.18 2015-04-29 13:46:21 PDT - Sort 02packages case insensitive, like PAUSE v1.0.17 2015-04-27 16:18:04 PDT - Add back warnings to Carton::CLI - Properly fail when a command is not found in carton exec (hachi) #193 v1.0.16 2015-04-25 06:37:17 PDT - update 02packages.details.txt whitespace padding to follow PAUSE v1.0.15 2015-04-20 11:13:32 CEST - downgrade some dependencies for fatpack-related tools to recommends (probably ship it as a separate distribution in the future) v1.0.14 2015-04-20 00:07:26 CEST - same as v1.0.14 v1.0.13 2015-04-19 19:38:42 CEST - require cpanm 1.7030 for better cpanfile support - switch to MakeMaker - remove Exception::Class and Moo in favor of Class::Tiny - add an ability to set generator in Carton::Index for Carmel use v1.0.12 2013-09-24 20:03:47 JST - up Path::Tiny - Add --no-fatpack to carton bundle #140 v1.0.11 2013-09-18 18:51:14 JST - Disable fatal warnings that comes with Moo. This will make Path::Tiny not fail on NFS without flock. #135 v1.0.10 2013-09-02 17:52:42 PDT - Documentation fixes - Support CRLF in snapshot (kan) #133 v1.0.9 2013-08-17 11:24:46 PDT - Workaround carton help shows wrong doc on case insensitive filesystems v1.0.8 2013-08-16 18:38:14 PDT - Include POD documentation for carton(1) v1.0.7 2013-08-10 21:55:29 PDT - Worked around fatpack issue with perl < 5.16 with missing File::Spec - Included missing requirements for fatpack executable v1.0.6 2013-08-10 17:59:51 PDT - Added upgrading documentation (carton help upgrading) - Experimental support for fatpacked carton executable in vendor/bin in bundle v1.0.5 2013-08-08 12:50:39 PDT - Bump cpanm for version extraction #126 - Fix doc about --cached (shibayu36) - Fix Usage errors #123 v1.0.4 2013-08-05 19:20:11 PDT - Bump cpanm to deal with failing to extract versions with version.pm #120 (lestrrat) v1.0.3 2013-08-05 10:17:59 PDT - Update obsolete docs - Added missing docs to some commands v1.0.2 2013-08-04 21:49:14 PDT - Bump cpanm dependency to deal with old dists with ancient META.yml (tokuhirom) v1.0.1 2013-08-04 17:10:10 PDT - Update docs - Fixed bug where version range requirements are not properly preserved in the snapshot #117 (lestrrat) v1.0.0 2013-08-04 12:29:31 PDT - This makes 1.0 release - Documentation update - Bump cpanm dependency v0.9.68 2013-07-26 17:49:28 PDT - Change the distribution name case, to match with the module name - Add Module::CoreList as a dependency for perl 5.8 v0.9.67 2013-07-24 14:53:53 PDT - Use cpanm's fatscript interface rather than share dir v0.9.66 2013-07-24 08:46:27 PDT - Correctly raises an exception when badly formatted snapshot file is read - Fixed a bug in tree scanner where seen hash is not preserved - tree scanner should be much faster for giant set of dependencies v0.9.65 2013-07-23 18:51:59 PDT - BIG CHANGE: Use cpanfile.snapshot instead of carton.lock for 1.0 onwards There is no way to migrate carton.lock to cpanfile.snapshot just yet. - New cpanfile.snapshot is text based and is more VCS friendly - Reworked internal of prereqs/requirements loader (again!) to eliminate lots of duplicate code v0.9.64 2013-07-23 14:39:54 PDT - Locate cpanm within a dist share dir so that cpanm in user's $PATH is not executed. This will solve issues with cpanm in /usr/bin, perlbrew or with bad shebang #92 v0.9.63 2013-07-23 02:26:04 PDT - Bump cpanminus requirement - Support --cpanfile for carton install - Support PERL_CARTON_CPANFILE (for commands other than install) v0.9.62 2013-07-22 14:33:11 PDT - Now all carton commands can be run from a subdirectory #69 - Refactored the way cpanfile/carton.lock files are detected v0.9.61 2013-07-22 10:24:35 PDT - Implemented experimental --without option for carton install v0.9.60 2013-06-26 12:22:21 PDT - Bump MakeMaker and Module::Build dependencies to support test requires v0.9.59 2013-06-17 17:13:21 PDT - carton exec -Ilib gives a warning, while carton exec perl -Ilib won't #97 v0.9.58 2013-06-10 03:17:23 PDT - Fix tests - carton exec without an arg should raise an error - typo fixes v0.9.57 2013-06-05 19:21:17 JST - Changed the output of carton tree command to include module and dist versions - Bunch of refactorings around requirements - carton install now saves tarballs in local/cache, then carton bundle copies from there - Implement carton check which checks if cpanfile requirements is satisfied locally with lock - Implement carton update! - Fix the installation collector logic to ignore dists that don't satisfy cpanfile v0.9.56 2013-06-04 00:21:53 JST - Fixed carton tree output to avoid duplicates v0.9.55 2013-06-03 23:43:52 JST - Added back carton tree command - Added --distfile option to list command v0.9.54 2013-06-02 12:38:20 JST - Install develop phase dependencies by default with carton install - carton exec now doesn't set PERL5OPT with lib::core::only, so as not to mess with the subprocess and site_perl modules (#60, #70, #82) v0.9.53 2013-06-01 23:54:53 JST - use Moo - refactored installer/downloader as Carton::Builder v0.9.52 2013-06-01 17:01:51 JST - carton exec doesn't need '--' before perl anymore #77 - remove even more unused code - backed out color output support - stopped collecting dependencies from cpanfile, since cpanm installdeps can read it directly - Temporarily disabled check command for now - Upped cpanm dependency - Use vendor/cache for bundling since local is most likely gitignored #88 - carton exec now requires carton install beforehand v0.9.51 2013-05-31 09:02:58 JST - Documentation fixes - Fixes test dependencies and build system v0.9.50 2013-05-31 02:18:07 JST - Documentation fixes - remove bunch of code that is unused - removed tree command for now - Overhauled the way bundle command works - refactored lock and index generation code - Enabled Travis CI tests v0.9.15 2013-03-31 18:11:28 PDT - Add minimum perl dependency v0.9.14 2013-03-30 18:25:39 PDT - Unset $VERSION on PAUSE (Thanks andk) v0.9.13 2013-03-30 15:14:49 PDT - repackage for better META files with Milla v0.9.3 v0.9.12 2013-03-30 15:01:55 PDT - repackage to set $VERSION v0.9.11 2013-03-30 14:54:21 PDT - Ignore 'perl' requirements so as it won't fail, for now. #71 - Install 'test' dependencies by default. #66 - Convert to Milla, do not install carton-* man pages v0.9.10 Tue Feb 26 13:32:34 PST 2013 - Same as v0.9_9. Still considered pre-1.0! v0.9_9 Wed Feb 6 11:02:46 PST 2013 - Fixed bundle command where it updated modules, not the versions specified in carton.lock. bundle now builds mirror files like install --deployment, and downloads tarballs for the specified versions. (vti) v0.9_8 Tue Feb 5 12:17:54 PST 2013 - Do not use carton.lock to build extra dependencies. Everything has to be pulled out of cpanfile, even with the deployment mode. This makes the deployment much more reliable, and could possibly work with differing os/perl versions across development and deployments. v0.9_7 Sat May 12 06:15:44 EEST 2012 - Experimental multiple mirror support (nihen) - Fixed cpanm dependency to avoid cascading bug v0.9_6 Thu May 10 21:05:35 CEST 2012 - use cpanfile + Module::Install for dogfooding - `carton` without args now does `carton install` (inspired by bundler) - Update bundle command to use install.json (masaki) - code cleanups and doc overhauls - removed `uninstall` command for now - Fixed CPAN::Meta::Requirements dependency v0.9_5 Thu Apr 12 19:39:19 JST 2012 - Added experimental cpanfile support - Fixed POD (yanick) v0.9.4 Sat Mar 31 13:49:41 CEST 2012 - use Capture::Tiny to capture output (wchristian) - Improve synopsis for exec (dagolden) - Implemented bundle command (masaki) - Fix Getopt::Long dependency (pfig) v0.9.3 Wed Oct 19 14:30:50 JST 2011 - Fixed META.yml by patching Module::Install and repackaging v0.9.2 Tue Oct 18 12:53:57 JST 2011 - Fixed packaging *again* by declaring version as a simple string via http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/ v0.9.1 Mon Oct 17 19:05:12 JST 2011 - Fixed packaging - Fixed UTF8 encoding warnings for JSON v0.9.0 Fri Oct 14 01:27:02 JST 2011 - Initial non-dev release. Still considered beta before it hits 1.0.0! v0.1_0 Sun Jun 26 11:03:50 PDT 2011 - original version Carton-v1.0.28/cpanfile000644 000765 000024 00000001300 12720763413 015663 0ustar00miyagawastaff000000 000000 on configure => sub { requires 'version', 0.77; }; requires 'perl', '5.8.5'; requires 'JSON', 2.53; requires 'Module::Metadata', 1.000003; requires 'Module::CPANfile', 0.9031; requires 'Try::Tiny', 0.09; requires 'parent', 0.223; requires 'Getopt::Long', 2.39; requires 'Class::Tiny', 1.001; requires 'Path::Tiny', 0.033; requires 'App::cpanminus', 1.7030; requires 'CPAN::Meta', 2.120921; requires 'CPAN::Meta::Requirements', 2.121; requires 'Module::CoreList'; # for fatpack requires 'Module::Reader', 0.002; recommends 'File::pushd'; recommends 'App::FatPacker', 0.009018; on develop => sub { requires 'Test::More', 0.90; requires 'Test::Requires'; requires 'Capture::Tiny'; }; Carton-v1.0.28/dist.ini000644 000765 000024 00000000055 12720763413 015631 0ustar00miyagawastaff000000 000000 name = Carton [@Milla] installer = MakeMaker Carton-v1.0.28/lib/000755 000765 000024 00000000000 12720763413 014733 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/LICENSE000644 000765 000024 00000043702 12720763413 015200 0ustar00miyagawastaff000000 000000 This software is copyright (c) 2011- by Tatsuhiko Miyagawa. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2011- by Tatsuhiko Miyagawa. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. END OF TERMS AND CONDITIONS Appendix: 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 humanity, 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 convey 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) 19yy 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 1, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2011- by Tatsuhiko Miyagawa. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Carton-v1.0.28/Makefile.PL000644 000765 000024 00000003361 12720763413 016142 0ustar00miyagawastaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.005. use strict; use warnings; use 5.008005; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Perl module dependency manager (aka Bundler for Perl)", "AUTHOR" => "Tatsuhiko Miyagawa", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "version" => "0.77" }, "DISTNAME" => "Carton", "EXE_FILES" => [ "script/carton" ], "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.008005", "NAME" => "Carton", "PREREQ_PM" => { "App::cpanminus" => "1.703", "CPAN::Meta" => "2.120921", "CPAN::Meta::Requirements" => "2.121", "Class::Tiny" => "1.001", "Getopt::Long" => "2.39", "JSON" => "2.53", "Module::CPANfile" => "0.9031", "Module::CoreList" => 0, "Module::Metadata" => "1.000003", "Module::Reader" => "0.002", "Path::Tiny" => "0.033", "Try::Tiny" => "0.09", "parent" => "0.223" }, "VERSION" => "v1.0.28", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "App::cpanminus" => "1.703", "CPAN::Meta" => "2.120921", "CPAN::Meta::Requirements" => "2.121", "Class::Tiny" => "1.001", "Getopt::Long" => "2.39", "JSON" => "2.53", "Module::CPANfile" => "0.9031", "Module::CoreList" => 0, "Module::Metadata" => "1.000003", "Module::Reader" => "0.002", "Path::Tiny" => "0.033", "Try::Tiny" => "0.09", "parent" => "0.223" ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Carton-v1.0.28/MANIFEST000644 000765 000024 00000002561 12720763413 015322 0ustar00miyagawastaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.005. Changes LICENSE MANIFEST META.json META.yml Makefile.PL README cpanfile dist.ini lib/Carton.pm lib/Carton/Builder.pm lib/Carton/CLI.pm lib/Carton/CPANfile.pm lib/Carton/Dependency.pm lib/Carton/Dist.pm lib/Carton/Dist/Core.pm lib/Carton/Doc/Bundle.pod lib/Carton/Doc/Check.pod lib/Carton/Doc/Exec.pod lib/Carton/Doc/FAQ.pod lib/Carton/Doc/Fatpack.pod lib/Carton/Doc/Install.pod lib/Carton/Doc/List.pod lib/Carton/Doc/Show.pod lib/Carton/Doc/Tree.pod lib/Carton/Doc/Update.pod lib/Carton/Doc/Upgrading.pod lib/Carton/Doc/Version.pod lib/Carton/Environment.pm lib/Carton/Error.pm lib/Carton/Index.pm lib/Carton/Mirror.pm lib/Carton/Package.pm lib/Carton/Packer.pm lib/Carton/Snapshot.pm lib/Carton/Snapshot/Emitter.pm lib/Carton/Snapshot/Parser.pm lib/Carton/Tree.pm lib/Carton/Util.pm script/carton t/author-pod-syntax.t xt/CLI.pm xt/cli/bundle.t xt/cli/check.t xt/cli/cpanfile.t xt/cli/deployment.t xt/cli/deps_phase.t xt/cli/exec.t xt/cli/freeze.t xt/cli/help.t xt/cli/install.t xt/cli/json_pp.t xt/cli/mirror.t xt/cli/mismatch.t xt/cli/no_cpanfile.t xt/cli/perl.t xt/cli/snapshot.t xt/cli/subdir.t xt/cli/tree.t xt/cli/update.t xt/cli/version.t xt/cli/without.t xt/mirror/authors/id/M/MI/MIYAGAWA/Hash-MultiValue-0.08.tar.gz xt/mirror/modules/02packages.details.txt xt/mirror/modules/02packages.details.txt.gz Carton-v1.0.28/META.json000644 000765 000024 00000005622 12720763413 015613 0ustar00miyagawastaff000000 000000 { "abstract" : "Perl module dependency manager (aka Bundler for Perl)", "author" : [ "Tatsuhiko Miyagawa" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.005, Dist::Milla version v1.0.16, CPAN::Meta::Converter version 2.150005", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Carton", "no_index" : { "directory" : [ "eg", "examples", "inc", "share", "t", "xt" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0", "version" : "0.77" } }, "develop" : { "requires" : { "Capture::Tiny" : "0", "Dist::Milla" : "v1.0.16", "Test::More" : "0.9", "Test::Pod" : "1.41", "Test::Requires" : "0" } }, "runtime" : { "recommends" : { "App::FatPacker" : "0.009018", "File::pushd" : "0" }, "requires" : { "App::cpanminus" : "1.703", "CPAN::Meta" : "2.120921", "CPAN::Meta::Requirements" : "2.121", "Class::Tiny" : "1.001", "Getopt::Long" : "2.39", "JSON" : "2.53", "Module::CPANfile" : "0.9031", "Module::CoreList" : "0", "Module::Metadata" : "1.000003", "Module::Reader" : "0.002", "Path::Tiny" : "0.033", "Try::Tiny" : "0.09", "parent" : "0.223", "perl" : "v5.8.5" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/perl-carton/carton/issues" }, "homepage" : "https://github.com/perl-carton/carton", "repository" : { "type" : "git", "url" : "https://github.com/perl-carton/carton.git", "web" : "https://github.com/perl-carton/carton" } }, "version" : "v1.0.28", "x_contributors" : [ "Christian Walde ", "David Golden ", "David Steinbrunner ", "Jonathan Steinert ", "Jose Luis Martinez ", "Kan Fushihara ", "Masahiro Chiba ", "NAKAGAWA Masaki ", "Olaf Alders ", "Pedro Figueiredo ", "Pedro Melo ", "Peter Oliver ", "shiba_yu36 ", "Tatsuhiko Miyagawa ", "Tatsuhiko Miyagawa ", "WATANABE Hiroaki ", "Yanick Champoux " ] } Carton-v1.0.28/META.yml000644 000765 000024 00000003555 12720763413 015446 0ustar00miyagawastaff000000 000000 --- abstract: 'Perl module dependency manager (aka Bundler for Perl)' author: - 'Tatsuhiko Miyagawa' build_requires: {} configure_requires: ExtUtils::MakeMaker: '0' version: '0.77' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.005, Dist::Milla version v1.0.16, CPAN::Meta::Converter version 2.150005' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Carton no_index: directory: - eg - examples - inc - share - t - xt recommends: App::FatPacker: '0.009018' File::pushd: '0' requires: App::cpanminus: '1.703' CPAN::Meta: '2.120921' CPAN::Meta::Requirements: '2.121' Class::Tiny: '1.001' Getopt::Long: '2.39' JSON: '2.53' Module::CPANfile: '0.9031' Module::CoreList: '0' Module::Metadata: '1.000003' Module::Reader: '0.002' Path::Tiny: '0.033' Try::Tiny: '0.09' parent: '0.223' perl: v5.8.5 resources: bugtracker: https://github.com/perl-carton/carton/issues homepage: https://github.com/perl-carton/carton repository: https://github.com/perl-carton/carton.git version: v1.0.28 x_contributors: - 'Christian Walde ' - 'David Golden ' - 'David Steinbrunner ' - 'Jonathan Steinert ' - 'Jose Luis Martinez ' - 'Kan Fushihara ' - 'Masahiro Chiba ' - 'NAKAGAWA Masaki ' - 'Olaf Alders ' - 'Pedro Figueiredo ' - 'Pedro Melo ' - 'Peter Oliver ' - 'shiba_yu36 ' - 'Tatsuhiko Miyagawa ' - 'Tatsuhiko Miyagawa ' - 'WATANABE Hiroaki ' - 'Yanick Champoux ' Carton-v1.0.28/README000644 000765 000024 00000011312 12720763413 015043 0ustar00miyagawastaff000000 000000 NAME Carton - Perl module dependency manager (aka Bundler for Perl) SYNOPSIS # On your development environment > cat cpanfile requires 'Plack', '0.9980'; requires 'Starman', '0.2000'; > carton install > git add cpanfile cpanfile.snapshot > git commit -m "add Plack and Starman" # Other developer's machine, or on a deployment box > carton install > carton exec starman -p 8080 myapp.psgi AVAILABILITY Carton only works with perl installation with the complete set of core modules. If you use perl installed by a vendor package with modules stripped from core, Carton is not expected to work correctly. Also, Carton requires you to run your command/application with carton exec command, which means it's difficult or impossible to run in an embedded perl use case such as mod_perl. DESCRIPTION carton is a command line tool to track the Perl module dependencies for your Perl application. Dependencies are declared using cpanfile format, and the managed dependencies are tracked in a cpanfile.snapshot file, which is meant to be version controlled, and the snapshot file allows other developers of your application will have the exact same versions of the modules. For cpanfile syntax, see cpanfile documentation. TUTORIAL Initializing the environment carton will use the local directory to install modules into. You're recommended to exclude these directories from the version control system. > echo local/ >> .gitignore > git add cpanfile cpanfile.snapshot > git commit -m "Start using carton" Tracking the dependencies You can manage the dependencies of your application via cpanfile. # cpanfile requires 'Plack', '0.9980'; requires 'Starman', '0.2000'; And then you can install these dependencies via: > carton install The modules are installed into your local directory, and the dependencies tree and version information are analyzed and saved into cpanfile.snapshot in your directory. Make sure you add cpanfile and cpanfile.snapshot to your version controlled repository and commit changes as you update dependencies. This will ensure that other developers on your app, as well as your deployment environment, use exactly the same versions of the modules you just installed. > git add cpanfile cpanfile.snapshot > git commit -m "Added Plack and Starman" Deploying your application Once you've done installing all the dependencies, you can push your application directory to a remote machine (excluding local and .carton) and run the following command: > carton install --deployment This will look at the cpanfile.snapshot and install the exact same versions of the dependencies into local, and now your application is ready to run. The --deployment flag makes sure that carton will only install modules and versions available in your snapshot, and won't fallback to query for CPAN Meta DB for missing modules. Bundling modules carton can bundle all the tarballs for your dependencies into a directory so that you can even install dependencies that are not available on CPAN, such as internal distribution aka DarkPAN. > carton bundle will bundle these tarballs into vendor/cache directory, and > carton install --cached will install modules using this local cache. Combined with --deployment option, you can avoid querying for a database like CPAN Meta DB or downloading files from CPAN mirrors upon deployment time. PERL VERSIONS When you take a snapshot in one perl version and deploy on another (different) version, you might have troubles with core modules. The simplest solution, which might not work for everybody, is to use the same version of perl in the development and deployment. To enforce that, you're recommended to use plenv and .perl-version to lock perl versions in development. You can also specify the minimum perl required in cpanfile: requires 'perl', '5.16.3'; and carton (and cpanm) will give you errors when deployed on hosts with perl lower than the specified version. COMMUNITY https://github.com/perl-carton/carton Code repository, Wiki and Issue Tracker irc://irc.perl.org/#cpanm IRC chat room AUTHOR Tatsuhiko Miyagawa COPYRIGHT Tatsuhiko Miyagawa 2011- LICENSE This software is licensed under the same terms as Perl itself. SEE ALSO cpanm cpanfile Bundler pip npm perlrocks only Carton-v1.0.28/script/000755 000765 000024 00000000000 12720763413 015471 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/t/000755 000765 000024 00000000000 12720763413 014430 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/000755 000765 000024 00000000000 12720763413 014620 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/cli/000755 000765 000024 00000000000 12720763413 015367 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/CLI.pm000644 000765 000024 00000002330 12720763413 015563 0ustar00miyagawastaff000000 000000 package xt::CLI; use strict; use base qw(Exporter); our @EXPORT = qw(run cli); use Test::Requires qw( Capture::Tiny File::pushd ); sub cli { my $cli = Carton::CLI::Tested->new; $cli->dir( Path::Tiny->tempdir(CLEANUP => !$ENV{NO_CLEANUP}) ); warn "Temp directory: ", $cli->dir, "\n" if $ENV{NO_CLEANUP}; $cli; } package Carton::CLI::Tested; use Carton::CLI; use Capture::Tiny qw(capture); use File::pushd (); use Path::Tiny; $Carton::CLI::UseSystem = 1; use Class::Tiny qw( dir stdout stderr exit_code ); sub write_file { my($self, $file, @args) = @_; $self->dir->child($file)->spew(@args); } sub write_cpanfile { my($self, @args) = @_; $self->write_file(cpanfile => @args); } sub run_in_dir { my($self, $dir, @args) = @_; local $self->{dir} = $self->dir->child($dir); $self->run(@args); } sub run { my($self, @args) = @_; my $pushd = File::pushd::pushd $self->dir; my @capture = capture { my $code = eval { Carton::CLI->new->run(@args) }; $self->exit_code($@ ? 255 : $code); }; $self->stdout($capture[0]); $self->stderr($capture[1]); } sub clean_local { my $self = shift; $self->dir->child("local")->remove_tree({ safe => 0 }); } 1; Carton-v1.0.28/xt/mirror/000755 000765 000024 00000000000 12720763413 016132 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/authors/000755 000765 000024 00000000000 12720763413 017617 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/modules/000755 000765 000024 00000000000 12720763413 017602 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/modules/02packages.details.txt000644 000765 000024 00000003070 12720763413 023707 0ustar00miyagawastaff000000 000000 File: 02packages.details.txt URL: http://www.perl.com/CPAN/modules/02packages.details.txt Description: Package names found in carton.lock Columns: package name, version, path Intended-For: Automated fetch routines, namespace documentation. Written-By: Carton v0.9.0 Line-Count: 16 Last-Updated: Wed Jun 29 22:54:55 2011 CGI 3.55 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Apache 1.01 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Carp 3.51 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Cookie 1.30 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Fast 1.08 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Pretty 3.46 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Push 1.05 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Switch 1.01 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGI::Util 3.53 M/MA/MARKSTOS/CGI.pm-3.55.tar.gz CGITempFile undef M/MA/MARKSTOS/CGI.pm-3.55.tar.gz FCGI 0.73 F/FL/FLORA/FCGI-0.73.tar.gz FCGI::Stream undef F/FL/FLORA/FCGI-0.73.tar.gz Fh undef M/MA/MARKSTOS/CGI.pm-3.55.tar.gz Hash::MultiValue 0.08 M/MI/MIYAGAWA/Hash-MultiValue-0.08.tar.gz MultipartBuffer undef M/MA/MARKSTOS/CGI.pm-3.55.tar.gz Try::Tiny 0.09 D/DO/DOY/Try-Tiny-0.09.tar.gz Carton-v1.0.28/xt/mirror/modules/02packages.details.txt.gz000644 000765 000024 00000001010 12720763413 024316 0ustar00miyagawastaff000000 000000  N02packages.details.txtr0z,iѝ áL.55ؒG^ҧInbԩf$:d\G2hD~ϲovR4Di+MVOVUePͭj@E-[r0NDi Fhb*W-uA#/Ҷ4Lԅ,XNR rJ˶ A&w Dgmr1A^:I4Gm4S4_.Z&PN3nx& +J[Y p>3ݜݴS؁dFʺ᳕Ze,c,)~aJQߴ qV7і/\ꗨg-Kwv>yi+2wi֞9*.&DŽLtP{7648Carton-v1.0.28/xt/mirror/authors/id/000755 000765 000024 00000000000 12720763413 020213 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/authors/id/M/000755 000765 000024 00000000000 12720763413 020407 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/authors/id/M/MI/000755 000765 000024 00000000000 12720763413 020714 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/authors/id/M/MI/MIYAGAWA/000755 000765 000024 00000000000 12720763413 022113 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/xt/mirror/authors/id/M/MI/MIYAGAWA/Hash-MultiValue-0.08.tar.gz000644 000765 000024 00000134416 12720763413 026606 0ustar00miyagawastaff000000 000000 4ItKHash-MultiValue-0.08.tar=ks۶Z TMFLirƵ&vrNn'h xL,ZV}|]/=LOiZ"\Nv^%D4w_}OvoFk6nYmw_WI1,e~m4I#X{)oXto6:]`=56W'|[yٵ@ |4Xȏh~&^\kOza&TaA69LrM3{pjXt,̇" .cn `[#HS~X5E(f@+e!`-cj^/x3 4>jºAuYkw{"LREi}|!g&l¾i.`~_aG@x/zSpo{.GCVE3yMK,;5L<ċoW/Tgu 4t'"hInUoTfIjJ-&@?<;}~ҿ|mC|>d1+5=~]tă5-{kN XӚ5Bq+s0ZCwmԮԸ^nk3v*mGh̓K>|HѶ~f-5mU6|הZaʶ/N_Xj`Ί3) } ~R:ЗCH&S_ّoݨHľ=<;RlK΃0_so1k77!>;;;JsGXp13Dl{U51W}%W2xW!{eh~HlWI;iu!C'7| X7=ӂ<챆S8w"0Q^ < S2yX"J]y ְoU:"0M5߱ﱉRQowW!m&#Fa<8)ڹn{g1xFav-`qi޳mM7*F;^ nHGFXnBXjrŵmd4]=tN 6~7e6cXha6y{.V9;( b7suoq'aȁesc=dS[( ٓʫOCy-[3U v30~RJUߞVNskX;OoAoqIl k8>PX*  U'Aa0g|.`]b HPSXr]B`5Y7)#.mzv^y4!h2:UB|"@pkhSRA^0Nы6+ll1  @0+peua5SM8Oaquk?\yTAT݌(HyM *2&įH8΄@),KDxxV9;۟KUk,ebnŲ2R"f]Q+4"]I9: 2uAz0S 䵶)yǸ ͅ rDVx4Z9:X˛LJg?˓˾" &LB? PKFPN|i+Aʥ,;LHB4 0O -pK۶Qۋ Eu0™6[r(Gaywݭ,T)@i`}!Zҁ1JdFQc@ Og$9;3'S4y(`UYk2 ).KۻREFUn]aH/[є`cpA6;]e2@5L[#ꥦ^`l2eI]rV/(Rr܏ , tE!diLhPNN~c} Pfp!-\HL+t.)pʀit@=}e<.`^ /{f^ʜS"U@3}|/g-{ ZZUJA-4@J VCtLL#5) ꘢I)YN:a Ov|)zY*@Vƌ%% c!IP֤װS~/jȂ"e DJ9E #X_oeoEy:0L-d\ْ$i* MkVd+5GNՉBp2l2hϳH˺qtnkf^-4<^=Y``v2.;ڄ\Ey\&GaEY qCoPpdl60Sa:6,6jz%3TxKi"]">zic h{l/!8B2 0xנJYF":aJIkB8?rR#g[tMmFH\#3X j2,0拘%iհA3uc&a>yi0MfymzQ&Ugm¿2aSdUefgfVڥm=/' -#`E=سANevj|M־SNA@|}'ڸF cQ){SOgz hMܒ@Xv)c* 2r梂k/L$DLNx0AAD m,Jzū%lRɏ8a4Q_`+ Lb_[g:>6u<(V%4n,dm@}txZū!%7FT֥J~D' nj5%]|OW13--?TaiؾXy) )e F2R} ɻo[XZa.T{oJ&:~,jvRq`L?t\CX0*bIj _n#̅&bdd\{y тhP·(ipq /+A1-F~-3ܰP6/)Q 宸v~EH ͏1!RyKPŦ)6=uOo>F$Pt?K /e-1Kyf6T}e EX;z4~ bsgg,u&ٍ8m9 1i_^-@N"lSM$Op#P#ax} ?2[T14aaEVb*deZ믩qj\cbf2iC=;d:LU0YfE ZpCl 5>%״\R;ʯhhIky)ۨ(Kw_{!ygBj5ԑQmd6`z,|Y;#{ }|wS};fе \"_A~˅TM|`MKac)9H|oH b!A*@q7mL.vJ̛G0{b 9}J97p>p[ \IICVa,zK}756>mnq O}jx-GѝՋʭ߲9FV;"b5yEXN4xp &+ZVJmsKO0@ݛ ;?/|˚vQGMf :e\%}]QTo~zowZ|_}{}_hƮ)?mLݭ lg"=] fC~EpSz0@xY>)/ztoI_9]2_ m_mʍOH[Nh5^jzvͱr#yz`יI.eٹgl6L;}Sd tE/>1EjK4tS[K7Y:#2J^nM֦OC|_)`[:Q^~/dQ#nmk>w&CG_sϭk{o.q]{u-Si@/Ewo+4TsT -Wȁ+Dٯر^ZV*(Leco[7֯@@^iw7 l`%k_a?~_ooi-NoWQXzR 64ƀYyQ,Q% bχK ;c̩OpCg-w[GP%RECEKAc{1z&*J{cG7|5bp`lB%AKDv,g`$10 f?u d;}3_M4@D; 'Sc˱L+}yQvlM_mnog[_z^/eDۣ(% 7;xnNg;Nf}Mww+NCE|^"8(2_T6=鴖SKm]"D~?[c']<7 cS8ֽI>J0;~Tzʯ"Wa?o_6)z+gwEo!StU@?|0kq8y` ?PKh`R>D) GEg1Tc#m .1-kÌ ?c%ԶcOBuNҡ=Ш&ˀc^ ܞekGޏbL fΓI}3G"G8U$ElՇuVj뗿pzݨ4H3:~au*0H$֩4|0] Ґ:'x˽x[4YԻ7Gh2 osmxsok4j{ j@tq ,{- Y2G6{DXZó9;j.USD'3Scr8ծ $OTx]FTZ~ {@ 5$P|WyLeYU2ٍ4e )TbtU1j4_MTRWR׽ Ea1߶ݓ؏_>]&!2ͥi!bH ljZDQSs|C 'y_0@=t(~IKgs?l8v&F;Ϝl߶x%EJFEbq+0Q,?{ү3@D WZ>3Q _~+xE2(}oӦtSOu'+]fgC~"Bh/oP|`|V!(Gi@|K+h7j3("}H{Mm7xb][diPiwGP'E>! Ӯ`TQLkcٓ"7Q!V85镊<|,b2n4ɰyEHx,o. !JTL£xԮ}q@xFRA<-*EF+q;x'Xo92>?ݧY@vfuDƮ ^lкuhu%N.W">30 1!Jc}~ bŜsjG+-n(ܗ/%}pr7 #l[*vHr # l- \iqQD/%.w]tp فgqJM|K͚nec.gu[z{7[i8o fP#ntfQJ# ›͎Vm.,#Dq&-J*ْۮF|HmDi3Ӯ Vyqv51>/>gf++b=Ʀ,(6 ̮:`?͍v}arFf2Q2ٸ 20[KDe+Edw20#c<ttMͨw_y/Q|vv9n?Kl>lpڏTR(4[?~mtKyl$L‰y^BUzw˫߰$~@<8DUp/t*dF' 3s ~_6'}d$p'Tc}yEdYio:!W8H4Vw--m" /hUFE%NgtcA9Ne9qR%K5X.4"95T\IQUA5m7NCq UWV7r ە6Z°| Nl8BXE- ~zugw3"swE-脗O^V.gDE% *"t'0e-a E3Z%omt+Ơ8 OM"n=Lz2|;Y<5fyW]VBǚaH`d m()jhqЙC4hlH5.S4IQ84HD f` E܅S!w7 q`}d1z{ &hp4TY3 k9`췜Rlu@FJu߯ĝqvgԉshxsVTnrx'[htLV_͟'sbnr&5ٽYKgcnLC[Ҭ;Ԗ֍~ʝ'd-+0ĹybiZjvp; |LhiZ<I8{&[,op MAܩޮɡϯe egI2MvJ5.v};y7P,;jkšeNJKӻ3n״Bc&ˤFZI`d)vhE@{|j[lJlv؅y#؃[MnIKS#8BГl̾hA_c%cReȬ|ϙ8w"JNf (SFz;5Rf.4=A7=AjhkY2&7Bͫƃ L?gj_F[ $gsW~6g5rE݂R-%3MiբgYZ0 y Rr iUՒ2lQ-= 5\ٓ8ѝņhS uN*Йy8KOPWehj+vHȘVr'>!N:N"˭|h6O-,[}uC^<9dZ%3QZ#LI骴V.rO097qtLQeUAN3j5ܻ;sfD kM͢_DwP疮fEY݉u8goMXJ-ỹBsޢ5I؅^zҴoQ5gNik$oLx魉$ܜD33ӤMuQ0FJi9%!͓a!!HS/"#y^!MaxNWb8tU;zt;5TuJ3CglhhZ;*%Ķ=3׸ ˑ;n ՝/':fƗ/C2'ofp]漩4 `M+Fm[;6{OoqBjv蚳 H4Z]- i{u{ Mk P5&eWڱ=lDuO0iJEԑ/)Ve!ms2#'T*K5]\FY!?"% 1ᑷY\sbQj.Nm̷-Dt(a%q``ODZ#ig/9¸y/Jk"9 霋*QdыhL^("b2,x}@O_H35ؤ `*ШbT `pF#n 1+$pU??Gav /SZIe \r Va=cC}#)SM<1uo44әĄN9E1a.CzSZ̤v]Z5osݣ}cCiaAeȹXlu`'H+}"'%iQ/KS2TxZ "$ݩBj]'aOa*+zsPg]%&.Co+3yJY/5N,s%(˔ ;4ٕI| SuI%c',X] dOvbhps?e P֖M*gZy9-pӜ (aԫz$^lUxMuJB '5io惖է%'NJgLo畚dJbr%vbuNgBxab>w8ǠS֢8[+UBi4%HX=Lu&x~>~\˼*:S=YUi/Vbf]+1- &Eko;jnn.11_5ݍqNgT{Z7,h$6݋Tg%h!P%mx%4{跼Ri7<4zFe; Hse Ffy>%7ԡr@^q@$Ҝ~Р*.XJ6u]u :%k~}6OeHp(ĺ۟NcFQ%2ϪlQǩ<1O$3j5vBSUm@t*;wSscK*NdTPYQk D=v}CUf~ TYI֘U)#k0ԑWx aka8Px+A0I2!vl `,b{td0-5$keOR9fL'%6}35HOcHC-u|zKiѶ^jgbS.%x'ՐO;Ŏ9ms.G&+6!w/׀7xCMҘ\]n6$c>.SӻE w:M2?@{銙 maW?CNqZ%؞q×;䤢c> ^Kz;9&YCnÃ'T 0bg/$C!FsrLaa=J+L޵)Cnz C3hgg-mzr6g(;Zv *8]w z:W4;Xu}t ]WKM\DH`a>qJRf,:r80c&I<,CSL5vMSP. YPbrC5ޒ[Km"nnLTU8hw쪢ѐʇC11V#jٸUGP^D݌j uPp+\r͸$܇+h=JpUb}dz$(b '3%y3KaٷLkfV9\qk~.ї[*/UZ$)h#:lGkp` y/H$6VK?}VŐ2JBj<ޛe&üg',@]@bf =$0kF SyͶ~(ј^^Mr& `lL!8u-Q>rz2܄SP~Vnb:%E̓=Y5HfiLJ=XZwlkW4 L5pJpCpddQNlv!,.-D;:@kh- /6p@E!t.K߈~kmo -znK5h][8\ rBqZT**aw2 uD=X`.vavNKϢQ&])p|⟳7Go_x)COZ)U^J!sp!^1tDRນWsע ĉ*2PyqTi:U= j=w{U+T^GfW?m_.DU2UK7/dA~]B( vFOkΗ  rB.[.aG632]:j_fԸ7\v L>MˁBc먇I^{i3(ڮH\Gd-B`2XS=7E+#VO z`RQo;MeMR\ȣI_"5QOd.I~']ky_f3%+J\ *[F²ya:ácm8墉ePR&1b:|G5pwe;Wjvު;~s[|A"I({D*Qk͎V bmW8GIaid\muR)_7t6S 0{/2VۍTt|bWz' ўPo0o2է\Ϡ`W>eO $m1yN#ZG:ӣrةVPM.t1U$t'Q܊2gjSսۢN(tw)-H7cPc'듪ELO(Bh< |;qcFE]S=IZ ڲ\*=#P*T:9oⴒ{p;wM -L' n lj4b&-nyHQgԩl8ф|K:#ʰ)2%jyNwV$@(~P،ԀGb8̧V\/*X#,a0Zlٛ{{=3*I3)8HZ']+8DG (2B*V*5+nM-Ǽ߮=jُU3{z |O 7b 4V3 3 ,2̼UMb1pyrQ7Yk&xîuMX bjx:ǹ: 2}9smKK+ܲ$A}(ONݜ(zOL RY1W/Iېx0 )\sU- d$lYىEfإ&nmC!6{mKX~-Sqg92#jWIHGP#2+H0iN0HțF?jqFg(iQdL0pB/<;AQ~;Tꗫ7RdVÇ6#f!8WF8%1x6a+Zwh䧻]΃ lh%ϸƉW$aS "3]Ƕ8VyAAlWفg1|3e1AfP^"kJ#ҚTe as( rw۫"}lHtaO;:d_*KK}cq$UG*c)] ݓ?iTDN,A ,<븺STWWzD܂ٶ?DZ)d0rFrhAZ$ZPAd|=NPQyi:k$V[ಖHiqQdGgHFЈchJ@*-<5l:i #%*]A:V4dLD'\Ksru${AG U: {)5't{r~ ~6!*[maɟtݯuzw?ߛEb"t&AS+ʢ/khV~6z0U#$)a-w*Acī^8%D:i|ivb:aU֨שtun烅~3tpRk XarJԪKa9R'lՏ|YNdROR3fUH 1r B0슣1VJAxFx8'p蜈9հ#_ָLMsv?&c6\ahve#zG!oT3oQBw&iۮw 6cOxnuΘ5ԈbfD=B ] 0;,hx> s[kf8{`*{?l15ZVu+Z͙R\&q"{b % 9Z>NS뗿a>@l;Ѱ`QL'g*͇_!cg? kcf+f?l!Wk^k;"W?ѿѸo4Rd)K98_"ro 8]% I) ij\ħ%ACg5rmcn×65 JVpQgiê"u%óVgI̢8-ˋh( zp868Ʒjj%JA;ge}O 0郆;bQᡑ*6us #!bi{Sm׭pV2_|LO \&S$ݮ8dtn2z$9s8 Ȃ(O:\xs4"`0[1xiBw0kgk<>T[Y m"̩C"oΎw{ƞGb2l#'I}_ӮHڕei&b'R2'WN 5.7'?u\T`lxиnNzḘ+"/Ub]Qg 9A3Όֺ *S!"S/%l`lDuI#b3tnl3~zț"l*"G.BB9Ag""HD" 'v$$2*aKꇮ1! J8}Nl0/?V"I2]z+ǐ+x49x Q+L \8 K5H@\) v 5ێZF`KnC) s >-NU=.cJ  $x`L0Ϲ^>D#úkdߣ3ADĂ;}p/#&FAߎa%aW:IlDe|3M2 2#QFys 3]Ra ycS@&LU VX~ Z*b*]T5"FB:2d๐- SڅrvU<; a+XJI7$)<1XI27(YZ Di$zL#n[m9,@Xa@ ՛k54~@u[mv )$bFn6ז5$;FB8STCYpA%TGrsN5]cF?d便e6)Vdj>EN8"ʶ$3hCA~lałFp}+/(J%N<|G ځ$6y,gG^i35y~s:jǼnΔgB ]S3OX${ Iqߎ_;%,N`ٲ$[NP͎3hK*8o:9Y]m.X{A^(B}W6y2cI[,ZB'4ǸERۿh?3g ^H?w5a"z{,Ǽ 8(tρxeT Jh 6NNtlZw!vtm>`aX0'iTMOǢ`T1$ëC(@@  bX?c ӰoEpѣ@KZHzTb>;@p aiR )nV8 -C\"lϵryF eE_~Xi^JKWtݵ Ӆ.ApϹ&x0cPQ/xp4K}S/t7 GqʊܑC% g=rꌇ# ;7|nT}'xL/GѐKyMzQNz_׺O yjlG`D؄] ?[ [^Ӗ̘54M5#W9D*~VY @)'~dgʁ,`v$maAkEVחbme[&:j 8[Eщ;٧Z!;: zv>Fe4Θ"a0ZP@y ̘Bi oݥ.6c7S mmW0ƖpۿFIzeyQ UֲO=pCInt $9VD=żuJXQɍJ>\J&rW\J+M~2tHPu(y+mXO։U=CM9i-W >qMq.&In7{:]xzIҏvM#ܗI].SWܽe qQoƶh xh`N$TUZtӡ5S:Rk$o|uғN4Йɫ|H/,J099h|1Y$j%q8cb H _nbyytUBHHW!5jWkšҨqF;LJ|aejx|Qffsi A! 8,=ßnͼj=?ʦl:/ϯ? iyY[U6y'OIκ*[#.噗Dz]fݿNg9YsˏX&MTymc8&md[#Fs/:b,Jvj/G%w= K30J-Yz`MT!Iuk&xC.jxoD51F:Esϒł$5Kmy!6UitÉmYV2<\%ۊMThZ82@~pSrLa/7/ T~C-_ 2}N\}kmeKac ؁1GTɽҦ\w5;(r_YZ= F ,ԀhBW.?;._wߕzK ߇x9zI0ѝ۞ŠY<9<`HQ`)!fT5ӣX.Jtc9^l 2r;!ndݗBdV)MK+q28aNƅL@^8StPiIPX% &ZujIVbY?.7Ҩۥ%JDqBQ:wZ˼P ^]Ӫf~Dvu&u9skݻOm~Y77kQ CW0k0aq3eqHWp|'Zv?u#w4Z_"GR//<3(tM=sox}eΣOGd{/;Д, <5㩁$[9=PK3)g0[I+T|jC`VIF`qIrq,IH2o/ܪɢL9MtQYzñe8N2{[ Mֹ{o~F &ed7\v߫5^%4՜#lJ!W_=ЛT,o楢,Ĕ&z0(%Kq?b $) `O.B)AVw34b{&l~׭gOB-<9(9kWd{kS<^"xqTr'GQ-ҠYq5 $KmHI5qZbXzUfmcW֘5 m]^[uvip̱hK8ȍ輞drGS%.*DbT@8ULJѷʠ\gC ѧX U }^}dAϋ{*&'*DjHs*o1dhL,r#JoƃR4 'bŝN.W0!<ߞR@k*XXT`bCN7)Htd>"0U\93/^?e_]`: .rIwTf"O]'Ajvp)a79` U5]4H\[K}yֽ]e^EcDQX0K nCb5ōu} $9h$bD~ G _ ).IQR_D*Q@Ko@jA GctY'5³*#v1Fsk.7/`XpHS}pz[ՎA{yq[s.6OIn?F ;VfyǕT9.Zb?|#^P2)ぴzL>m,_rCW&|p[v\E䡐v3%kǖZΰh?VyFjrs˒|>PA(%÷u,J[$hNSZ;.Tzt>|68y[pw%KP=z Wߢ|L-0~s 6Z\7{;I4*Hzܳ\(zI4亜3X$mi6ײ<B$`nF$ 5EEb37=V>%Œ Pp-; :7?3rb#D號YeDbMgJ֭d|}n3wQ >[!B}rU* 3 b_[i% \^$a ƅգC]%So"~\t"Ru ȋ,U=JErO(dNҥt'u(Tg]G(Z3 O@la{/Aֆ0'E7ͻGh(G]N'' $_ kw}pG̈τA@ W,פx&޼s)FVRF}cŀlȺ헡UhD*8=@#e2l&,fN$%_'9izQCOaہoDv@zլ|m) ipFCsvX KVo,jfue[, i 0=XpdLTJl?~T.ID2ME]sxмZs\F⸆0Ԟ#o:-vTpdQqBF(vt{GgӾr 6ByX2zjcȃ'Gzz29~ ,FAW+7r0= ުu۝( XntHH-V3-GVsY*֒3bzlx !,\Я|903znueܲ8"ʂ9ive3IhFn4тٵZj$X3FJgXnZ19SʭW2YΔm`(|eJot>'!rGQs 5!;Jn8ji`WI -حU`_埒XUO!,,µS-7P.0-zdWejOe#1(yaXV2kC7fͲ{3 `` I<n^~A&|@LHYIۤZ~Y^4 nSĶ֩\j,o).L| yCZ1_,ݨ7D]T9]lU|GN6*)oUܨ ːa|IUDĨ.xC )8to69䉄[4ag$?Ak=kO,ffd;hȏ-=%s !cȩ +hH$OdVf CGF`VV@Jʞ}}re͂-Q=`Cd馯8:bF1ѣsNY"z8(.aUYG==^?BB;j6ۣ1bkkTOvC >Vu"Ihʼ!Y[H+2"ToIE'kdcQ nP )%D)@' ȫ7Tbonk*cXrbuZee%``if u9A4GsN&5%5|PufBDFvoy-ttrl2Q}nYݺybJPq8K``G\i[~ f)N2V8Qnpi6gd=v,@U퓏d, D"<o1wʖ}#eG%B2~xARJVi k!Qiq] 0 =':GNC|\Ug+0ɐ0NO2&MiɊh1/;yRkXdi:Ԍw?l)>H˃`k nDniY9;w4VIŽ,[/\٨V9^$Y~8|Ǵ5BAT/Ж9bO0v9K&!bJlC(j{ uVX*m{_J&-qO) %߁?j 5Y(,{ǒS7cXԲ\-s8RKey&D7~Vc۾_dv;eF7 vvq={snwNsGioõuҹSi}w/$0roUnvhGW}EDq:*t6'9b bT|4i Q#/./Js!~ 1mnfn ^m{/~RBLCG-o;3MRÔ`:FoSna:žW;]hdO1͈PFKB b.Yt# j/2,@_ɺD@`TA~gfߨeOglXh9ODd^F+x2Yݤ9 FU:<"}̧D @q&}Ww no{9ZoU@O! : ez5GA{f ۵=y 7LsR6V|iD_=0+I.qy9 ][Dk3 ^3 #]U*"G?<@#{qmWc/K L=/_5 z/V2z,W냧de_0n7i-)Zd{ɱCکaQ*R}a4DM;}+?fl qvtReU8>6ڂStYņb\GKf}'Ia d͑@@D0b2dlfpi-c!c҇{D-ubL>'bDQ(8 i/srQ@U8փtBJ+ʃ)hO< Vg= (%s:Vk#W sd5fӦ9A($sTy΋pJeէL WH.A8z&xAT'Çp >{T=@rZ#B|TG@|Hƌ2u XSa+d\*໱Ki _rRU'R[aTF|v Qyr$H|J)}T^ jB;b·<;ËDjf.4Tp(9'T#~ZP4tCSv@.&Qt$!mIN=\]!N=ǝJZJNBR"i?d!:V;ƏL<￧q=!H 9 3䏲qh1+PՊ1Wia( + gRp0FWj0|TZi@/+R"|Z$ad0E:6Qֿ7 t +&9,wU"OagkZP>m_'Dh.;؊|j %(T9M" \+ɏ`d1 7(W>}ze'чZ/]ք:dP!F+wĊm%ۓ7%~% 5!}kՔ#v+/rR+:o4lb qCPY34|˅Y 'gkŀ̼^tj1(Ђ\3 `Yqb9ѧBuy"A.E )2s dS:*D7sQ6\N4HoyQ17Ԍ#,/H Q^fG$h#2%q pPC񉒨SaS2DCcu X<=zІFȏ&pkOD )*C/< `Bd\x]}B7סGfZߟN*L'(6'V)`RЍF.ϝF(|q@c\I<3Hiα:RQYӜXh_oNY7 nY-UC4L+d!6oEԧ",Yظll6u/( %!I=in |ʚOA'T|HQ2@- Svtm fCDŒY1`]SQ}Y5C"D~p'LP nYb>+@S*chBxԼjH/F0Kը#VITd^=ɭ>]r0G\ԑw*=LM @u &ݘ!9URjgF;_`?#q&rhP/ٲiHJנ!"ɼ`VtR5ހ߬^ë P<"ۖ Z @f*`IL۱B7| 5lil 4m X>0 N*P>:!IV6BF+QhM^MW"ݥ^ AZr=zb[5X8uNk?- 'D緕Olpd3c:}ȸ2P2ӃSV!&\[s֬q-ӡYӱ#A(3k@p#)i2GA‡TFAXY~GOl +Egps Yrq#Ynó_A6TBÊ5=;?U]X4Tkː^pރk{j83ōi0&PCF/^,,( $C_-F]*7uNt0R Kl h`-3@݆i(jMv8E5iiHh!Ç#~u-~UZrܑ .\{_[SqTYMhN ltM̲&qS*³cA/HJQuDh2\lcnq#Q[Y'v Nzk[Lۙi4hiF|b-E9!nWnMԬ!]Tz8DlKġ,]7-4c8Qc'@i{쪙ۺ]z'w~Q5(U=mpABY3_[ r2H)ӽ$_mlY9W2@7/u4Xti ]tMxy i.2vug?L\[ywǹN>ӆ-9 Tǡ:zB~]< qNY(=zgvz3) ! mrӥbI[mͷƝ<;/%6\ƃϗ+IW>:⿍fgT۱mib:]a \m@T 髭ek]|T-݂(W: -N^c4F8$f\f㰤 "{5w9~{?5w*v]]Nj4Nzi 232u~WQvE_FL8vH' zŖF2{ W(8~LN^ߕ:`zU{#v;ߛrSrtaV)$[EMw8 ):xu!1 lK*@,izǝNyt^/;"^BSۯɅ!GjoD]r2;ZyV^nS#3l] RJNJ +ӎʃx7UEϒj˙j왪#8MTg@/:p_5?iUi.YѦ xf?lw_oؿRp)o3=˝o?/VA l=jWҰ;D7|%Dmi]"xC0s&ȶS."z-pUHԫyI:Q$}J'vDEhV{34hb~KsLE̹6^Y#*!p-srKn6Άr{4"uߠTtWYnQsҍVAo*`uvX1lqWN!f0h=lb[瓨(d=*͸gݵkMUkDK'$pՄ%"*-khDQ!daBz3JYP1¨E 3W͛UEA++@ powcGZTyq &8˂BH/{'Oc#Ѕ!E#Q߰Eϰ2Z ؁ʴ;AdDyӛ^?) DzM[mtsb7B#Ȏ$O8wk&LQd/¨~C4T %(h.`Qc}}rׯ4M.ZÎY@nYՠO:'it89!zڔdr,hTڛE58BfDTybrͨ'JyT‘`1`Zmz ts׈^̨kO-m \o8i |sLQ!HKz;S2P N3e M=0q݂Ί:3e 7O@q-VH2 &!rfAIgĀ24-gYvuKyN,O:J (FV'ih, 1 Zơ󁋑PtOYH)}ZM{,QK\>Yo]N+-Xr>ӝSܬJ\dZbLu;Ep[& DϳI;WxQ9'p/nKdųH]3s39_m$powTR*GsD-Df-;iߖb0l:0anU ֎gKIy8*s둧Z޷1=>9Z W ԟWOS3`DpxtRC-)g[7u"u\PwxY3]s ҿ[qIه]ݒo-;Vy x( ̤>0 7œgGh2H{ֆ*9 0YS%$˵],J"Y븰[Q͕v{rCoi5+nZ jx'd)3wnsDQ ?RpKr*id-, c- w?T`Xvs)C .CHQG$(+y$CJypDUFY 4A{W]~J!)u2&u4 [<S;s>` QvZqRhHFzՈk3ocJaK]&8| Zp˚eNO[dyK!۝%ƫu~՝Nd5H4@U&/"Ġjs+ ɀ!0=u'%H])y"sH_q? k` Bԣ[s^(|G`Vu+_⯴=3I,FSOlW[|*E#\R"O{|Xb7E(bb:)Q:s-w^<= 5V0!~tOZ4%y|!zooWa~q3'UakcwɃw;Ou+ÚǺWSt_CLR$^zذ3]ܟ鏊>p(){Kܜe[ަʖKӧ "VQ')Q_f\`>/g,d 9󣨕XDWZvOm}_]|Gdk43+39QD2t~ 5cw_Ke#3EG㷝!=I\-Qҿj1C]!荒J&IfbUDra״[\c L{ ¨9EBn57>EvNo-A#SPmuM"!rȝP)5/եqwȪa 2te!Rïuzbo&+뛽r"y$$RNL#T $FMދ'"z65n ס6Q?''hb{c=ĉHt%[\o[~gF5Bpv ??:"UT ~o!މWtteLqE! fsmaHA3s[JQ1X5xߊXo{p#Z\5z|/GwS[k-o|o`nU`TK395n -=<wH 6p=-X%|Ξ6Ts+470Km(kĀBizj.c5zz^`ºn 1X#_(S\8h7zR!;5jŴ`9bDsw5vSTv8͏/_#,D\)# Y^p%5iiLXy_ %dpT{\*^CH~iKB!Cmgs1c7DHJj^a Q%ziV:o(@:IF'C_먄J M!wmQ{{agol]mtx=2♏>a5W )`u|&" kPN8s$r]@+HISm)4!}=<"vc35qcQEʠҌټBSJ&QS0|6ǼFZ-6bnAQo9'd ;nA){^8,;J g(t)>Yɴϟ«(k}HnIxq8䁳BS],Dc Fs8UmTiVA@(#<C&pP<7NYAM!*9-/|߲.z2WScݮe{݋MOqݹeW6]I9Bmy1i0'XMWz.6SN0ejeNSFk(\uttퟧ 螄bҁ[{? y"79$m*IMks!'dA foqq>jcTekΖjViU_w&*VKW*LΟE:6AWnr|&|hҽD O/>Gi؆|r @і#5 O9rɏokpn?dhP$lq1YW\k`P&+bYq6DTZYB& ߇q NTKz1U>ʈsdQƉg\XFᕹ?麣.lg-f$'pQ|o]WU@HBP?4F ОȂ ё.~EH^vE xEw2;ajv"c]3^1 8ˉW3lٱ@>/I*zH'PBV{" =X_76ey,E8LWdЮ~EBhyCLVTwߜp|>EsZ7z=VV7pV>p]p~nau[Kp}Jy?v~vGz:6-tz'?5+mV#hM dJkӆi-pLKn2LF|K Kg(/#: &lasCӤeMLc FÇCgJĈ9/,3; O{S1QdG$eKE=8-tv TlP5xN7ce|GDҫt I13ڡ(JLZm"j,!ekG^ ʼbTQOiWe78lxO&;T=I hAX$n߽K+JuQ!EmJԚ~8F C'1̷PG%Iƣ Uo6L \e17O7Go_0g=]t~f xrtgo  SaKhnS F`lSVG!LG+TdKcFȋأ%iM1 =z2*a cKJn+II:t,.AC, Y{;Q[5`i"4(`,mJ٥%m[KI= 0P1bG.QvN ZNM_1e;P#L .adBYS=$bJ\,n#eDfڡA̖sfKH :;^ FO+UgG"6l˼9J 4u7 /lCgUmQiyMMڥ2]۶~|h=&8ycvfּgcmu +(:T 1ݜm!d| QPc1}%``4EV;B7+U_(g*xA=JTx]DU qVBRKuŒ>fخ>V~#廵]L[qO)fB40ehdM , 6QPBx24Hׯ_nv/8x# ~Y^Yʼn*AFkh@/J^5\/riூmz[^vXK(`M-N&) @O/$(vva0OlƽOoM hb#HZ{rxd z 4(/0iC =GgPg#+S#Q*y {Nawe&C߾0gsA;xMNC/ B.rrbs&h,Ή!0xK3:'F;f*1s>18<'vZ8pW D"G)kFGކG.$k{m4'%]i&3h|y֏QiTdx( gOG  {vZ sS3V|J8jc%b$ںr#!ʲyb65w0'e;Us [L<5Yݨ&ӑ jU/nzoTxi2w#]|bt!]ya a1DP8ɸG匘?s0F@-֨ p4($4GJAB_턯'0#>4ڠht٩gyv;w_ف):j ǰ(@ؓs=toF՘@9IUEiKmq͝n !%E7ﯮpl8 ~&m'!ܩVDUT\g4[=n3;WbB+D+s $/Xu7?X]TKĴF}܋OcR/s[J΅ը)j-0#p`WL {aa4O@?H=nvJiJY1V'ryVV1f{S$dABAk&Llj.‡ ӥ,?;q/eRb^}h1y]i[eL\F.ő⎩bj/Fu`,[|y"~,jJ( aABF I4 <;1Ɓ&pj.W~CYhچ Fh5K"Mζ8C$x `b l/sۥbvC͛vFX=[ ]򂡚8*f^WZm-ڵL{}$#NRKyļ(<~ /݌;'~[("X< \ 2kwTuM>+I{m JuKfoF2>orδYcP/l&zngyvFc]OĹ2AGҦ ӯb 6> ?vF9HS+xqS2Cb$6Ec.&>8M{MZ#4ew#Re)82'7jHӔAإP58`q`,:;q-uPB_`֚nƀVJsmn9[KzY^]9Wͯ"U1}r BA3cYE"tՒvbGĀ<@DUHӖuSU,7`KFP{&>(NT#T|0XANߗAlظӜLX=3|hIF݇0/ ^ : wfCjo0hбmm1=1cG@tm&Ӎ]֒#ڦh*yD&n҃Wh3E@l:G^)o{[or-3#F*ʝ[t.Q9ıϴl1Lflsi,I6ʹ5U֕22L>;b&cLF8e'#V"*frq3s_"oms}B8yW}ћyyL˺b3 )d:Rx|cǥ8l N7/%"6 35z  595χd[d%'1JrQph2Ap:)T<\ ::RM̳ 㺵yg\15Y *Ģ6gl3-Zcp.UA[0xtVSll)]\~.?Sj'THi$W9KЕkDTAmPm;W\L1ﺊEo,zǨXqZj\Ukl?XEە@J@{X hĔ>&MB3 龎ªpTWD[ +i@#Eoך§Y.J.;i!,HwংmYWs> 3`L>` ^-M?|h-:"ҞC""[G/Z!ƛU\ zQOh<I'E —"8\5wW:{Q[0<|3{A;3< đszmf7'RfEbm޶Jf79qƀBYP_#Ty^\VOzbvP#sFȆY1'$HR-?veDڏwwy:={bA"9=25'#UVEl"?ixݟgۼWjZ픠 _&;j($s*2q>R=>w`EÐՐTGt\|;PIʥ &1^vkXEl:@5HrI<>*`?|*xt ZZu:Rr9\d^䝣;=:Ъ?A&gd.ʴTf6D +Vl ,UaKe^a?zRSFӴ}ySdZDAVճgK^J^5sR%IdF%yP+Uq@qJʛs"w^oc-犃X?::Xލ #b.٦u ;w\6a2$#EW[j{ڜVm uƓا_ݏxr1=0mxݹ N6#NSqrRyvsę:k*}Lz'XQ0&/3 !MP*В=E%.+s[ce-CyEn‘_7 .̙&S<č!TL !("h&,Q4,lnUntaîo2l8 &ϝI2mwqB8#zzi{@EPKOJL+P+TMki|`[)X"@Do)@8h{f*5!pv DH+EJ 5ۂP{ NICb= Zh^PI.mZiuH?cpi0uOU*.ߴ{}@e݄HF*&jEQs hm7U!sQ |hU S6"BAK"G-eq[{_~j/ZXp&opcE4)1Az6@)&PX%a lV hP^$R:Ǚ>wj'%"= Ꭳh= τ`)}(>5lf?Uu &Ǐ>߄7"C$YfQPY?c`q?W7rs?r<&!/tbEr8fǶN#ɪk"4'ohaգ]0uhGR+Id\܈Ѭ^?S6wzFVrMlGxRo^>y= f֫8>G*=KXۭU=)H.yZ)j;~9pR *|ÅVt(n6 Ȓޣ$ x .Kl`ŰV1us H[k&(*W|@ٍ2b{2Yxˌdk#/TJ ԙ8 W NY<)]Qy*yizQGɳ* C4_ q+=l7XyBBI$wKt/8Q"D$DmpiYUYu2mν֦{ F3 M+o-+yfJ}R<`?GH1Nq/ZBNXHo`^tONW $UU, ۋ~|`3MS)!NHRA*w=b#+xݩW(ዧ/yUS#G=UBbھ47bRҤM]Zm'+ѺD M*upA3耧oIד_& g_q*=9[ 4?06d€5#rjU=,ɂI"ext`Dju) <ggW<@^\A8C*nKG LUf>\l7FW89瑱#!t{ :A!Ĉ E#3@I{BZtX$5c2 K߾DG!z`WQt7I1谍hMIW 'ShS)2A/lN$1C@fG0{gC}ēFѡh3vHJ@{m!{:g@L. 49I||mofqw/~:jZ7Dl2  ſ#6=è2@2waQ{ JB6~뻍owF^3vᴏ%,{LՂC%VG.pz~ptAU;E/W*addSx.;\ TZ3#" 9 ?X:MUBO>8IΖ_rfQ5/2%JW8b69TR01tX.juwo{q(=nw~>|G/?©zCN ;Z{cu|=W`9U1CseeGɖGlV!)G-" %Fw*$,d.L^v˻Ɨ(}%Mpކ{xTЖܢyR2u.@ xH3tcW3S`y1Hk-ߕyB6CarB1[ ""r9sd܈PyX"Q[2CoE Y Rn8W^2C%%Q:L-p_Ӏ99ć A;\5 G -=zMM:dN-s5eډAa& 2wAY La_8HE$ܚ3I5 G8@VE[09tֈvhY}5׿?qX*Carton-v1.0.28/xt/cli/bundle.t000644 000765 000024 00000000441 12720763413 017024 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("bundle"); ok -f ($app->dir . "/vendor/cache/authors/id/D/DO/DOY/Try-Tiny-0.12.tar.gz"); } done_testing; Carton-v1.0.28/xt/cli/check.t000644 000765 000024 00000003756 12720763413 016644 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton check fails when there is no lock' => sub { my $app = cli(); $app->write_cpanfile(<run("check"); like $app->stderr, qr/find cpanfile\.snapshot/; }; subtest 'carton install and check' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("check"); like $app->stdout, qr/are satisfied/; $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.11/; $app->write_cpanfile(<run("check"); like $app->stdout, qr/not satisfied/; TODO: { local $TODO = 'exec does not verify lock'; $app->run("exec", "perl", "use Try::Tiny"); like $app->stderr, qr/\.snapshot/; } $app->run("install"); $app->run("check"); like $app->stdout, qr/are satisfied/; $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.\d\d/; $app->write_cpanfile(<run("check"); like $app->stdout, qr/not satisfied/; $app->run("install"); like $app->stderr, qr/failed/; $app->run("check"); like $app->stdout, qr/not satisfied/; }; subtest 'detect unused modules' => sub { my $app = cli; $app->write_cpanfile("requires 'Try::Tiny';"); $app->run("install"); $app->write_cpanfile(""); TODO: { local $TODO = "Can't detect superflous modules"; $app->run("install"); $app->run("list"); is $app->stdout, ""; $app->run("check"); like $app->stdout, qr/unused/; } }; subtest 'detect downgrade' => sub { my $app = cli; $app->write_cpanfile("requires 'URI';"); $app->run("install"); $app->write_cpanfile("requires 'URI', '== 1.59';"); $app->run("check"); like $app->stdout, qr/not satisfied/; like $app->stdout, qr/URI has version .* Needs == 1\.59/; }; done_testing; Carton-v1.0.28/xt/cli/cpanfile.t000644 000765 000024 00000002134 12720763413 017335 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton install --cpanfile' => sub { my $app = cli(); $app->write_file('cpanfile.foo', <run("install", "--cpanfile", "cpanfile.foo"); $app->run("check", "--cpanfile", "cpanfile.foo"); ok !$app->dir->child('cpanfile.snapshot')->exists; ok $app->dir->child('cpanfile.foo.snapshot')->exists; like $app->stdout, qr/are satisfied/; local $ENV{PERL_CARTON_CPANFILE} = $app->dir->child('cpanfile.foo')->absolute; $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.11/; $app->run("exec", "perl", "-e", "use Try::Tiny\ 1"); like $app->stderr, qr/Try::Tiny .* 0\.11/; }; subtest 'PERL_CARTON_CPANFILE' => sub { my $app = cli(); local $ENV{PERL_CARTON_CPANFILE} = $app->dir->child('cpanfile.foo')->absolute; $app->write_file('cpanfile.foo', <run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.11/; ok $app->dir->child('cpanfile.foo.snapshot')->exists; }; done_testing; Carton-v1.0.28/xt/cli/deployment.t000644 000765 000024 00000001026 12720763413 017733 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(<run("install", "--deployment"); like $app->stderr, qr/deployment requires cpanfile\.snapshot/; $app->run("install"); $app->clean_local; $app->run("install", "--deployment"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.11/; $app->run("exec", "perl", "-e", "use Try::Tiny 2;"); like $app->stderr, qr/Try::Tiny.* version 0\.11/; } done_testing; Carton-v1.0.28/xt/cli/deps_phase.t000644 000765 000024 00000000660 12720763413 017671 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(< sub { requires 'Test::NoWarnings'; recommends 'Test::Pretty'; }; on develop => sub { requires 'Path::Tiny'; }; EOF $app->run("install"); $app->run("list"); like $app->stdout, qr/Test-NoWarnings/; like $app->stdout, qr/Path-Tiny/; unlike $app->stdout, qr/Test-Pretty/; } done_testing; Carton-v1.0.28/xt/cli/exec.t000644 000765 000024 00000004270 12720763413 016503 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton exec without a command', sub { my $app = cli(); $app->write_cpanfile(''); $app->run("install"); $app->run("exec"); like $app->stderr, qr/carton exec needs a command/; is $app->exit_code, 255; }; subtest 'exec without cpanfile', sub { my $app = cli(); $app->run("exec", "perl", "-e", 1); like $app->stderr, qr/Can't locate cpanfile/; is $app->exit_code, 255; }; subtest 'exec without a snapshot', sub { my $app = cli(); $app->write_cpanfile(); $app->run("exec", "perl", "-e", 1); like $app->stderr, qr/cpanfile\.snapshot/; is $app->exit_code, 255; }; subtest 'carton exec', sub { my $app = cli(); $app->write_cpanfile(''); $app->run("install"); TODO: { local $TODO = "exec now does not strip site_perl"; $app->run("exec", "perl", "-e", "use Try::Tiny"); like $app->stderr, qr/Can't locate Try\/Tiny.pm/; } $app->write_cpanfile(<run("install"); $app->run("exec", "--", "perl", "-e", 'use Try::Tiny; print $Try::Tiny::VERSION, "\n"'); like $app->stdout, qr/0\.11/; $app->run("exec", "perl", "-e", 'use Try::Tiny; print $Try::Tiny::VERSION, "\n"'); like $app->stdout, qr/0\.11/, "No need for -- as well"; $app->run("exec", "perl", "-MTry::Tiny", "-e", 'print $Try::Tiny::VERSION, "\n"'); like $app->stdout, qr/0\.11/; $app->write_cpanfile(<run("install"); $app->run("exec", "--", "ack", "--version"); like $app->stdout, qr/ack 2\.02/; }; subtest 'carton exec perl -Ilib', sub { my $app = cli(); $app->write_cpanfile(''); $app->run("install"); $app->dir->child("lib")->mkpath; $app->dir->child("lib/FooBarBaz.pm")->spew("package FooBarBaz; 1"); $app->run("exec", "perl", "-Ilib", "-e", 'use FooBarBaz; print "foo"'); like $app->stdout, qr/foo/; unlike $app->stderr, qr/exec -Ilib is deprecated/; $app->run("exec", "-Ilib", "perl", "-e", 'print "foo"'); like $app->stdout, qr/foo/; like $app->stderr, qr/exec -Ilib is deprecated/; }; done_testing; Carton-v1.0.28/xt/cli/freeze.t000644 000765 000024 00000000554 12720763413 017040 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.11/; $app->clean_local; $app->run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.11/; } done_testing; Carton-v1.0.28/xt/cli/help.t000644 000765 000024 00000001001 12720763413 016474 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->run("help"); like $app->stdout, qr/Carton - Perl module/; $app->run("-h"); like $app->stdout, qr/Carton - Perl module/; $app->run("help", "install"); like $app->stdout, qr/Install the dependencies/; $app->run("install", "-h"); like $app->stdout, qr/Install the dependencies/; $app->run("help", "foobarbaz"); is $app->stdout, ''; like $app->stderr, qr/No documentation found/; } done_testing; Carton-v1.0.28/xt/cli/install.t000644 000765 000024 00000002706 12720763413 017227 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton install with version range' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("tree"); like $app->stdout, qr/Try::Tiny/; unlike $app->stderr, qr/Could not parse snapshot file/; }; subtest 'meta info for ancient modules' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/Algorithm-Diff/; }; subtest 'meta info for modules with version->declare' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("check"); SKIP: { skip "MakeMaker installs CPAN::Meta and fails on carton check", 2 if $] < 5.14; like $app->stdout, qr/are satisfied/; unlike $app->stderr, qr/is not installed/; } }; subtest 'meta info for modules with qv()' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("check"); SKIP: { skip "MakeMaker installs CPAN::Meta and fails on carton check", 2 if $] < 5.14; like $app->stdout, qr/are satisfied/; unlike $app->stderr, qr/is not installed/; } }; done_testing; Carton-v1.0.28/xt/cli/json_pp.t000644 000765 000024 00000000556 12720763413 017232 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; plan skip_all => "perl <= 5.14" if $] >= 5.015; { my $app = cli(); $app->write_cpanfile(<run("install"); $app->clean_local; $app->run("install", "--deployment"); unlike $app->stderr, qr/JSON::PP is not in range/; } done_testing; Carton-v1.0.28/xt/cli/mirror.t000644 000765 000024 00000001106 12720763413 017064 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; my $cwd = Path::Tiny->cwd; { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/^Hash-MultiValue-0.08/m; } { # fallback to CPAN my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/^PSGI-/m; } done_testing; Carton-v1.0.28/xt/cli/mismatch.t000644 000765 000024 00000000643 12720763413 017364 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(< '== 2.139'; requires 'Test::Differences' => '== 0.61'; EOF $app->run("install"); $app->run("list"); like $app->stdout, qr/Data-Dumper-2\.139/; like $app->stdout, qr/Test-Differences-0\.61/; $app->run("check"); like $app->stdout, qr/are satisfied/; } done_testing; Carton-v1.0.28/xt/cli/no_cpanfile.t000644 000765 000024 00000000274 12720763413 020034 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->run("install"); like $app->stderr, qr/Can't locate cpanfile/; is $app->exit_code, 255; } done_testing; Carton-v1.0.28/xt/cli/perl.t000644 000765 000024 00000000467 12720763413 016525 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(<run("install"); like $app->stdout, qr/Complete/; $app->run("list"); like $app->stdout, qr/Hash-MultiValue-/; } done_testing; Carton-v1.0.28/xt/cli/snapshot.t000644 000765 000024 00000002704 12720763413 017416 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'snapshot file has canonical representation' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); my $content = $app->dir->child('cpanfile.snapshot')->slurp; for (1..3) { $app->dir->child('cpanfile.snapshot')->remove; $app->run("install"); is $content, $app->dir->child('cpanfile.snapshot')->slurp; } }; subtest 'Bad snapshot version' => sub { my $app = cli(); $app->write_cpanfile(''); $app->write_file('cpanfile.snapshot', <run("install"); like $app->stderr, qr/Could not parse/; }; subtest 'Bad snapshot file' => sub { my $app = cli(); $app->write_cpanfile(''); $app->write_file('cpanfile.snapshot', <run("install"); like $app->stderr, qr/Could not parse/; }; subtest 'snapshot file support separate CRLF' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); my $content = $app->dir->child('cpanfile.snapshot')->slurp; $content =~ s/\n/\r\n/g; $app->write_file('cpanfile.snapshot', $content); $app->run("install"); ok !$app->stderr; }; done_testing; Carton-v1.0.28/xt/cli/subdir.t000644 000765 000024 00000001000 12720763413 017033 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton exec in subdir', sub { my $app = cli(); $app->write_cpanfile(<run('install'); $app->dir->child('x')->mkpath; $app->run_in_dir('x' => 'list'); like $app->stdout, qr/Try-Tiny/; $app->run_in_dir('x' => 'check'); like $app->stdout, qr/are satisfied/; $app->run_in_dir('x' => 'install'); like $app->stdout, qr/Complete/; unlike $app->stderr, qr/failed/; }; done_testing; Carton-v1.0.28/xt/cli/tree.t000644 000765 000024 00000000527 12720763413 016517 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("tree"); is $app->exit_code, 0; like $app->stdout, qr/^HTML::Parser \(HTML-Parser-/m; like $app->stdout, qr/^ HTML::Tagset \(HTML-Tagset-/m; } done_testing; Carton-v1.0.28/xt/cli/update.t000644 000765 000024 00000003221 12720763413 017034 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton update NonExistentModule' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("update", "XYZ"); like $app->stderr, qr/Could not find module XYZ/; }; subtest 'carton update upgrades a dist' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.09/; $app->write_cpanfile(<= 0.09, <= 0.12'; EOF $app->run("install"); $app->run("check"); like $app->stdout, qr/are satisfied/; $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.09/; $app->run("update", "Try::Tiny"); like $app->stdout, qr/installed Try-Tiny-0\.12.*upgraded from 0\.09/; $app->run("check"); like $app->stdout, qr/are satisfied/; $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.12/; }; subtest 'downgrade a distribution' => sub { my $app = cli(); $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.\d\d/; $app->write_cpanfile(<run("update"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.09/; TODO: { local $TODO = 'collecting wrong install info'; $app->write_cpanfile(<run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-0\.09/; } }; done_testing; Carton-v1.0.28/xt/cli/version.t000644 000765 000024 00000000223 12720763413 017236 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; my $app = cli(); $app->run("version"); like $app->stdout, qr/carton $Carton::VERSION/; done_testing; Carton-v1.0.28/xt/cli/without.t000644 000765 000024 00000003104 12720763413 017255 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use xt::CLI; subtest 'carton install --without develop' => sub { my $app = cli(); $app->write_cpanfile(< sub { requires 'Hash::MultiValue', '== 0.14'; }; EOF $app->run("install"); $app->run("list"); like $app->stdout, qr/Try-Tiny-/; like $app->stdout, qr/Hash-MultiValue-0\.14/; $app->run("exec", "perl", "-e", "use Hash::MultiValue\ 1"); like $app->stderr, qr/Hash::MultiValue .* version 0.14/; $app->clean_local; $app->run("install", "--without", "develop"); $app->run("list"); like $app->stdout, qr/Try-Tiny-/; TODO: { local $TODO = "--without is not remembered for list"; unlike $app->stdout, qr/Hash-MultiValue-/; } $app->run("exec", "perl", "-e", "use Hash::MultiValue\ 1"); unlike $app->stderr, qr/Hash::MultiValue .* version 0.14/; }; subtest 'without features' => sub { my $app = cli(); $app->write_cpanfile(< sub { requires 'Stream::Buffered', '== 0.01'; }; EOF $app->run("install"); $app->run("list"); like $app->stdout, qr/Stream-Buffered-0\.01/; $app->clean_local; $app->run("install", "--deployment"); $app->run("exec", "perl", "-e", "use Stream::Buffered 1"); like $app->stderr, qr/Stream::Buffered .* version 0\.01/; $app->clean_local; $app->run("install", "--without", "stream"); $app->run("exec", "perl", "-e", "use Stream::Buffered 1"); unlike $app->stderr, qr/Stream::Buffered .* version 0\.01/; }; done_testing; Carton-v1.0.28/t/author-pod-syntax.t000644 000765 000024 00000000503 12720763413 020221 0ustar00miyagawastaff000000 000000 #!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); Carton-v1.0.28/script/carton000755 000765 000024 00000000551 12720763413 016706 0ustar00miyagawastaff000000 000000 #!perl use strict; use 5.008001; use Carton::CLI; exit Carton::CLI->new->run(@ARGV); __END__ =head1 NAME carton - Perl module dependency manager =head1 SYNOPSIS > carton install > carton exec ./myscript =head1 DESCRIPTION For more documentation, refer to L by running C or C. =head1 SEE ALSO L =cut Carton-v1.0.28/lib/Carton/000755 000765 000024 00000000000 12720763413 016161 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/lib/Carton.pm000644 000765 000024 00000011243 12720763413 016520 0ustar00miyagawastaff000000 000000 package Carton; use strict; use 5.008_005; use version; our $VERSION = version->declare("v1.0.28"); 1; __END__ =head1 NAME Carton - Perl module dependency manager (aka Bundler for Perl) =head1 SYNOPSIS # On your development environment > cat cpanfile requires 'Plack', '0.9980'; requires 'Starman', '0.2000'; > carton install > git add cpanfile cpanfile.snapshot > git commit -m "add Plack and Starman" # Other developer's machine, or on a deployment box > carton install > carton exec starman -p 8080 myapp.psgi =head1 AVAILABILITY Carton only works with perl installation with the complete set of core modules. If you use perl installed by a vendor package with modules stripped from core, Carton is not expected to work correctly. Also, Carton requires you to run your command/application with C command, which means it's difficult or impossible to run in an embedded perl use case such as mod_perl. =head1 DESCRIPTION carton is a command line tool to track the Perl module dependencies for your Perl application. Dependencies are declared using L format, and the managed dependencies are tracked in a I file, which is meant to be version controlled, and the snapshot file allows other developers of your application will have the exact same versions of the modules. For C syntax, see L documentation. =head1 TUTORIAL =head2 Initializing the environment carton will use the I directory to install modules into. You're recommended to exclude these directories from the version control system. > echo local/ >> .gitignore > git add cpanfile cpanfile.snapshot > git commit -m "Start using carton" =head2 Tracking the dependencies You can manage the dependencies of your application via C. # cpanfile requires 'Plack', '0.9980'; requires 'Starman', '0.2000'; And then you can install these dependencies via: > carton install The modules are installed into your I directory, and the dependencies tree and version information are analyzed and saved into I in your directory. Make sure you add I and I to your version controlled repository and commit changes as you update dependencies. This will ensure that other developers on your app, as well as your deployment environment, use exactly the same versions of the modules you just installed. > git add cpanfile cpanfile.snapshot > git commit -m "Added Plack and Starman" =head2 Deploying your application Once you've done installing all the dependencies, you can push your application directory to a remote machine (excluding I and I<.carton>) and run the following command: > carton install --deployment This will look at the I and install the exact same versions of the dependencies into I, and now your application is ready to run. The C<--deployment> flag makes sure that carton will only install modules and versions available in your snapshot, and won't fallback to query for CPAN Meta DB for missing modules. =head2 Bundling modules carton can bundle all the tarballs for your dependencies into a directory so that you can even install dependencies that are not available on CPAN, such as internal distribution aka DarkPAN. > carton bundle will bundle these tarballs into I directory, and > carton install --cached will install modules using this local cache. Combined with C<--deployment> option, you can avoid querying for a database like CPAN Meta DB or downloading files from CPAN mirrors upon deployment time. =head1 PERL VERSIONS When you take a snapshot in one perl version and deploy on another (different) version, you might have troubles with core modules. The simplest solution, which might not work for everybody, is to use the same version of perl in the development and deployment. To enforce that, you're recommended to use L and C<.perl-version> to lock perl versions in development. You can also specify the minimum perl required in C: requires 'perl', '5.16.3'; and carton (and cpanm) will give you errors when deployed on hosts with perl lower than the specified version. =head1 COMMUNITY =over 4 =item L Code repository, Wiki and Issue Tracker =item L IRC chat room =back =head1 AUTHOR Tatsuhiko Miyagawa =head1 COPYRIGHT Tatsuhiko Miyagawa 2011- =head1 LICENSE This software is licensed under the same terms as Perl itself. =head1 SEE ALSO L L L L L L L =cut Carton-v1.0.28/lib/Carton/Builder.pm000644 000765 000024 00000006035 12720763413 020111 0ustar00miyagawastaff000000 000000 package Carton::Builder; use strict; use Class::Tiny { mirror => undef, index => undef, cascade => sub { 1 }, without => sub { [] }, cpanfile => undef, fatscript => sub { $_[0]->_build_fatscript }, }; sub effective_mirrors { my $self = shift; # push default CPAN mirror always, as a fallback # TODO don't pass fallback if --cached is set? my @mirrors = ($self->mirror); push @mirrors, Carton::Mirror->default if $self->custom_mirror; push @mirrors, Carton::Mirror->new('http://backpan.perl.org/'); @mirrors; } sub custom_mirror { my $self = shift; ! $self->mirror->is_default; } sub bundle { my($self, $path, $cache_path, $snapshot) = @_; for my $dist ($snapshot->distributions) { my $source = $path->child("cache/authors/id/" . $dist->pathname); my $target = $cache_path->child("authors/id/" . $dist->pathname); if ($source->exists) { warn "Copying ", $dist->pathname, "\n"; $target->parent->mkpath; $source->copy($target) or warn "$target: $!"; } else { warn "Couldn't find @{[ $dist->pathname ]}\n"; } } } sub install { my($self, $path) = @_; $self->run_cpanm( "-L", $path, (map { ("--mirror", $_->url) } $self->effective_mirrors), ( $self->index ? ("--mirror-index", $self->index) : () ), ( $self->cascade ? "--cascade-search" : () ), ( $self->custom_mirror ? "--mirror-only" : () ), "--save-dists", "$path/cache", $self->groups, "--cpanfile", $self->cpanfile, "--installdeps", $self->cpanfile->dirname, ) or die "Installing modules failed\n"; } sub groups { my $self = shift; # TODO support --without test (don't need test on deployment) my @options = ('--with-all-features', '--with-develop'); for my $group (@{$self->without}) { push @options, '--without-develop' if $group eq 'develop'; push @options, "--without-feature=$group"; } return @options; } sub update { my($self, $path, @modules) = @_; $self->run_cpanm( "-L", $path, (map { ("--mirror", $_->url) } $self->effective_mirrors), ( $self->custom_mirror ? "--mirror-only" : () ), "--save-dists", "$path/cache", @modules ) or die "Updating modules failed\n"; } sub _build_fatscript { my $self = shift; my $fatscript; if ($Carton::Fatpacked) { require Module::Reader; my $content = Module::Reader::module_content('App::cpanminus::fatscript') or die "Can't locate App::cpanminus::fatscript"; $fatscript = Path::Tiny->tempfile; $fatscript->spew($content); } else { require Module::Metadata; $fatscript = Module::Metadata->find_module_by_name("App::cpanminus::fatscript") or die "Can't locate App::cpanminus::fatscript"; } return $fatscript; } sub run_cpanm { my($self, @args) = @_; local $ENV{PERL_CPANM_OPT}; !system $^X, $self->fatscript, "--quiet", "--notest", @args; } 1; Carton-v1.0.28/lib/Carton/CLI.pm000644 000765 000024 00000024523 12720763413 017134 0ustar00miyagawastaff000000 000000 package Carton::CLI; use strict; use warnings; use Config; use Getopt::Long; use Path::Tiny; use Try::Tiny; use Module::CoreList; use Scalar::Util qw(blessed); use Carton; use Carton::Builder; use Carton::Mirror; use Carton::Snapshot; use Carton::Util; use Carton::Environment; use Carton::Error; use constant { SUCCESS => 0, INFO => 1, WARN => 2, ERROR => 3 }; our $UseSystem = 0; # 1 for unit testing use Class::Tiny { verbose => undef, carton => sub { $_[0]->_build_carton }, mirror => sub { $_[0]->_build_mirror }, }; sub _build_mirror { my $self = shift; Carton::Mirror->new($ENV{PERL_CARTON_MIRROR} || $Carton::Mirror::DefaultMirror); } sub run { my($self, @args) = @_; my @commands; my $p = Getopt::Long::Parser->new( config => [ "no_ignore_case", "pass_through" ], ); $p->getoptionsfromarray( \@args, "h|help" => sub { unshift @commands, 'help' }, "v|version" => sub { unshift @commands, 'version' }, "verbose!" => sub { $self->verbose($_[1]) }, ); push @commands, @args; my $cmd = shift @commands || 'install'; my $code = try { my $call = $self->can("cmd_$cmd") or Carton::Error::CommandNotFound->throw(error => "Could not find command '$cmd'"); $self->$call(@commands); return 0; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ($_->isa('Carton::Error::CommandExit')) { return $_->code || 255; } elsif ($_->isa('Carton::Error::CommandNotFound')) { warn $_->error, "\n\n"; $self->cmd_usage; return 255; } elsif ($_->isa('Carton::Error')) { warn $_->error, "\n"; return 255; } }; return $code; } sub commands { my $self = shift; no strict 'refs'; map { s/^cmd_//; $_ } grep { /^cmd_.*/ && $self->can($_) } sort keys %{__PACKAGE__."::"}; } sub cmd_usage { my $self = shift; $self->print(< where is one of: @{[ join ", ", $self->commands ]} Run carton -h for help. HELP } sub parse_options { my($self, $args, @spec) = @_; my $p = Getopt::Long::Parser->new( config => [ "no_auto_abbrev", "no_ignore_case" ], ); $p->getoptionsfromarray($args, @spec); } sub parse_options_pass_through { my($self, $args, @spec) = @_; my $p = Getopt::Long::Parser->new( config => [ "no_auto_abbrev", "no_ignore_case", "pass_through" ], ); $p->getoptionsfromarray($args, @spec); # with pass_through keeps -- in args shift @$args if $args->[0] && $args->[0] eq '--'; } sub printf { my $self = shift; my $type = pop; my($temp, @args) = @_; $self->print(sprintf($temp, @args), $type); } sub print { my($self, $msg, $type) = @_; my $fh = $type && $type >= WARN ? *STDERR : *STDOUT; print {$fh} $msg; } sub error { my($self, $msg) = @_; $self->print($msg, ERROR); Carton::Error::CommandExit->throw; } sub cmd_help { my $self = shift; my $module = $_[0] ? ("Carton::Doc::" . ucfirst $_[0]) : "Carton.pm"; system "perldoc", $module; } sub cmd_version { my $self = shift; $self->print("carton $Carton::VERSION\n"); } sub cmd_bundle { my($self, @args) = @_; my $env = Carton::Environment->build; $env->snapshot->load; $self->print("Bundling modules using @{[$env->cpanfile]}\n"); my $builder = Carton::Builder->new( mirror => $self->mirror, cpanfile => $env->cpanfile, ); $builder->bundle($env->install_path, $env->vendor_cache, $env->snapshot); $self->printf("Complete! Modules were bundled into %s\n", $env->vendor_cache, SUCCESS); } sub cmd_fatpack { my($self, @args) = @_; my $env = Carton::Environment->build; require Carton::Packer; Carton::Packer->new->fatpack_carton($env->vendor_bin); } sub cmd_install { my($self, @args) = @_; my($install_path, $cpanfile_path, @without); $self->parse_options( \@args, "p|path=s" => \$install_path, "cpanfile=s" => \$cpanfile_path, "without=s" => sub { push @without, split /,/, $_[1] }, "deployment!" => \my $deployment, "cached!" => \my $cached, ); my $env = Carton::Environment->build($cpanfile_path, $install_path); $env->snapshot->load_if_exists; if ($deployment && !$env->snapshot->loaded) { $self->error("--deployment requires cpanfile.snapshot: Run `carton install` and make sure cpanfile.snapshot is checked into your version control.\n"); } my $builder = Carton::Builder->new( cascade => 1, mirror => $self->mirror, without => \@without, cpanfile => $env->cpanfile, ); # TODO: --without with no .lock won't fetch the groups, resulting in insufficient requirements if ($deployment) { $self->print("Installing modules using @{[$env->cpanfile]} (deployment mode)\n"); $builder->cascade(0); } else { $self->print("Installing modules using @{[$env->cpanfile]}\n"); } # TODO merge CPANfile git to mirror even if lock doesn't exist if ($env->snapshot->loaded) { my $index_file = $env->install_path->child("cache/modules/02packages.details.txt"); $index_file->parent->mkpath; $env->snapshot->write_index($index_file); $builder->index($index_file); } if ($cached) { $builder->mirror(Carton::Mirror->new($env->vendor_cache)); } $builder->install($env->install_path); unless ($deployment) { $env->cpanfile->load; $env->snapshot->find_installs($env->install_path, $env->cpanfile->requirements); $env->snapshot->save; } $self->print("Complete! Modules were installed into @{[$env->install_path]}\n", SUCCESS); } sub cmd_show { my($self, @args) = @_; my $env = Carton::Environment->build; $env->snapshot->load; for my $module (@args) { my $dist = $env->snapshot->find($module) or $self->error("Couldn't locate $module in cpanfile.snapshot\n"); $self->print( $dist->name . "\n" ); } } sub cmd_list { my($self, @args) = @_; my $format = 'name'; $self->parse_options( \@args, "distfile" => sub { $format = 'distfile' }, ); my $env = Carton::Environment->build; $env->snapshot->load; for my $dist ($env->snapshot->distributions) { $self->print($dist->$format . "\n"); } } sub cmd_tree { my($self, @args) = @_; my $env = Carton::Environment->build; $env->snapshot->load; $env->cpanfile->load; my %seen; my $dumper = sub { my($dependency, $reqs, $level) = @_; return if $level == 0; return Carton::Tree::STOP if $dependency->dist->is_core; return Carton::Tree::STOP if $seen{$dependency->distname}++; $self->printf( "%s%s (%s)\n", " " x ($level - 1), $dependency->module, $dependency->distname, INFO ); }; $env->tree->walk_down($dumper); } sub cmd_check { my($self, @args) = @_; my $cpanfile_path; $self->parse_options( \@args, "cpanfile=s" => \$cpanfile_path, ); my $env = Carton::Environment->build($cpanfile_path); $env->snapshot->load; $env->cpanfile->load; # TODO remove snapshot # TODO pass git spec to Requirements? my $merged_reqs = $env->tree->merged_requirements; my @missing; for my $module ($merged_reqs->required_modules) { my $install = $env->snapshot->find_or_core($module); if ($install) { unless ($merged_reqs->accepts_module($module => $install->version_for($module))) { push @missing, [ $module, 1, $install->version_for($module) ]; } } else { push @missing, [ $module, 0 ]; } } if (@missing) { $self->print("Following dependencies are not satisfied.\n", INFO); for my $missing (@missing) { my($module, $unsatisfied, $version) = @$missing; if ($unsatisfied) { $self->printf(" %s has version %s. Needs %s\n", $module, $version, $merged_reqs->requirements_for_module($module), INFO); } else { $self->printf(" %s is not installed. Needs %s\n", $module, $merged_reqs->requirements_for_module($module), INFO); } } $self->printf("Run `carton install` to install them.\n", INFO); Carton::Error::CommandExit->throw; } else { $self->print("cpanfile's dependencies are satisfied.\n", INFO); } } sub cmd_update { my($self, @args) = @_; my $env = Carton::Environment->build; $env->cpanfile->load; my $cpanfile = Module::CPANfile->load($env->cpanfile); @args = grep { $_ ne 'perl' } $env->cpanfile->required_modules unless @args; $env->snapshot->load; my @modules; for my $module (@args) { my $dist = $env->snapshot->find_or_core($module) or $self->error("Could not find module $module.\n"); next if $dist->is_core; push @modules, "$module~" . $env->cpanfile->requirements_for_module($module); } return unless @modules; my $builder = Carton::Builder->new( mirror => $self->mirror, cpanfile => $env->cpanfile, ); $builder->update($env->install_path, @modules); $env->snapshot->find_installs($env->install_path, $env->cpanfile->requirements); $env->snapshot->save; } sub cmd_run { my($self, @args) = @_; local $UseSystem = 1; $self->cmd_exec(@args); } sub cmd_exec { my($self, @args) = @_; my $env = Carton::Environment->build; $env->snapshot->load; # allows -Ilib @args = map { /^(-[I])(.+)/ ? ($1,$2) : $_ } @args; while (@args) { if ($args[0] eq '-I') { warn "exec -Ilib is deprecated. You might want to run: carton exec perl -Ilib ...\n"; splice(@args, 0, 2); } else { last; } } $self->parse_options_pass_through(\@args); # to handle -- unless (@args) { $self->error("carton exec needs a command to run.\n"); } # PERL5LIB takes care of arch my $path = $env->install_path; local $ENV{PERL5LIB} = "$path/lib/perl5"; local $ENV{PATH} = "$path/bin:$ENV{PATH}"; if ($UseSystem) { system @args; } else { exec @args; exit 127; # command not found } } 1; Carton-v1.0.28/lib/Carton/CPANfile.pm000644 000765 000024 00000002064 12720763413 020102 0ustar00miyagawastaff000000 000000 package Carton::CPANfile; use Path::Tiny (); use Module::CPANfile; use overload q{""} => sub { $_[0]->stringify }, fallback => 1; use subs 'path'; use Class::Tiny { path => undef, _cpanfile => undef, requirements => sub { $_[0]->_build_requirements }, }; sub stringify { shift->path->stringify(@_) } sub dirname { shift->path->dirname(@_) } sub prereqs { shift->_cpanfile->prereqs(@_) } sub required_modules { shift->requirements->required_modules(@_) } sub requirements_for_module { shift->requirements->requirements_for_module(@_) } sub path { my $self = shift; if (@_) { $self->{path} = Path::Tiny->new($_[0]); } else { $self->{path}; } } sub load { my $self = shift; $self->_cpanfile( Module::CPANfile->load($self->path) ); } sub _build_requirements { my $self = shift; my $reqs = CPAN::Meta::Requirements->new; $reqs->add_requirements($self->prereqs->requirements_for($_, 'requires')) for qw( configure build runtime test develop ); $reqs->clear_requirement('perl'); $reqs; } 1; Carton-v1.0.28/lib/Carton/Dependency.pm000644 000765 000024 00000000512 12720763413 020573 0ustar00miyagawastaff000000 000000 package Carton::Dependency; use strict; use Class::Tiny { module => undef, requirement => undef, dist => undef, }; sub requirements { shift->dist->requirements(@_) } sub distname { my $self = shift; $self->dist->name; } sub version { my $self = shift; $self->dist->version_for($self->module); } 1; Carton-v1.0.28/lib/Carton/Dist/000755 000765 000024 00000000000 12720763413 017064 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/lib/Carton/Dist.pm000644 000765 000024 00000001377 12720763413 017432 0ustar00miyagawastaff000000 000000 package Carton::Dist; use strict; use Class::Tiny { name => undef, pathname => undef, provides => sub { +{} }, requirements => sub { $_[0]->_build_requirements }, }; use CPAN::Meta; sub add_string_requirement { shift->requirements->add_string_requirement(@_) } sub required_modules { shift->requirements->required_modules(@_) } sub requirements_for_module { shift->requirements->requirements_for_module(@_) } sub is_core { 0 } sub distfile { my $self = shift; $self->pathname; } sub _build_requirements { CPAN::Meta::Requirements->new; } sub provides_module { my($self, $module) = @_; exists $self->provides->{$module}; } sub version_for { my($self, $module) = @_; $self->provides->{$module}{version}; } 1; Carton-v1.0.28/lib/Carton/Doc/000755 000765 000024 00000000000 12720763413 016666 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/lib/Carton/Environment.pm000644 000765 000024 00000004657 12720763413 021037 0ustar00miyagawastaff000000 000000 package Carton::Environment; use strict; use Carton::CPANfile; use Carton::Snapshot; use Carton::Error; use Carton::Tree; use Path::Tiny; use Class::Tiny { cpanfile => undef, snapshot => sub { $_[0]->_build_snapshot }, install_path => sub { $_[0]->_build_install_path }, vendor_cache => sub { $_[0]->_build_vendor_cache }, tree => sub { $_[0]->_build_tree }, }; sub _build_snapshot { my $self = shift; Carton::Snapshot->new(path => $self->cpanfile . ".snapshot"); } sub _build_install_path { my $self = shift; if ($ENV{PERL_CARTON_PATH}) { return Path::Tiny->new($ENV{PERL_CARTON_PATH}); } else { return $self->cpanfile->path->parent->child("local"); } } sub _build_vendor_cache { my $self = shift; Path::Tiny->new($self->install_path->dirname . "/vendor/cache"); } sub _build_tree { my $self = shift; Carton::Tree->new(cpanfile => $self->cpanfile, snapshot => $self->snapshot); } sub vendor_bin { my $self = shift; $self->vendor_cache->parent->child('bin'); } sub build_with { my($class, $cpanfile) = @_; $cpanfile = Path::Tiny->new($cpanfile)->absolute; if ($cpanfile->is_file) { return $class->new(cpanfile => Carton::CPANfile->new(path => $cpanfile)); } else { Carton::Error::CPANfileNotFound->throw(error => "Can't locate cpanfile: $cpanfile"); } } sub build { my($class, $cpanfile_path, $install_path) = @_; my $self = $class->new; $cpanfile_path &&= Path::Tiny->new($cpanfile_path)->absolute; my $cpanfile = $self->locate_cpanfile($cpanfile_path || $ENV{PERL_CARTON_CPANFILE}); if ($cpanfile && $cpanfile->is_file) { $self->cpanfile( Carton::CPANfile->new(path => $cpanfile) ); } else { Carton::Error::CPANfileNotFound->throw(error => "Can't locate cpanfile: (@{[ $cpanfile_path || 'cpanfile' ]})"); } $self->install_path( Path::Tiny->new($install_path)->absolute ) if $install_path; $self; } sub locate_cpanfile { my($self, $path) = @_; if ($path) { return Path::Tiny->new($path)->absolute; } my $current = Path::Tiny->cwd; my $previous = ''; until ($current eq '/' or $current eq $previous) { # TODO support PERL_CARTON_CPANFILE my $try = $current->child('cpanfile'); if ($try->is_file) { return $try->absolute; } ($previous, $current) = ($current, $current->parent); } return; } 1; Carton-v1.0.28/lib/Carton/Error.pm000644 000765 000024 00000001341 12720763413 017607 0ustar00miyagawastaff000000 000000 package Carton::Error; use strict; use overload '""' => sub { $_[0]->error }; use Carp; sub throw { my($class, @args) = @_; die $class->new(@args); } sub rethrow { die $_[0]; } sub new { my($class, %args) = @_; bless \%args, $class; } sub error { $_[0]->{error} || ref $_[0]; } package Carton::Error::CommandNotFound; use parent 'Carton::Error'; package Carton::Error::CommandExit; use parent 'Carton::Error'; sub code { $_[0]->{code} } package Carton::Error::CPANfileNotFound; use parent 'Carton::Error'; package Carton::Error::SnapshotParseError; use parent 'Carton::Error'; sub path { $_[0]->{path} } package Carton::Error::SnapshotNotFound; use parent 'Carton::Error'; sub path { $_[0]->{path} } 1; Carton-v1.0.28/lib/Carton/Index.pm000644 000765 000024 00000002730 12720763413 017570 0ustar00miyagawastaff000000 000000 package Carton::Index; use strict; use Class::Tiny { _packages => sub { +{} }, generator => sub { require Carton; "Carton $Carton::VERSION" }, }; sub add_package { my($self, $package) = @_; $self->_packages->{$package->name} = $package; # XXX ||= } sub count { my $self = shift; scalar keys %{$self->_packages}; } sub packages { my $self = shift; sort { lc $a->name cmp lc $b->name } values %{$self->_packages}; } sub write { my($self, $fh) = @_; print $fh <generator ]} Line-Count: @{[ $self->count ]} Last-Updated: @{[ scalar localtime ]} EOF for my $p ($self->packages) { print $fh $self->_format_line($p->name, $p->version_format, $p->pathname); } } sub _format_line { my($self, @row) = @_; # from PAUSE::mldistwatch::rewrite02 my $one = 30; my $two = 8; if (length $row[0] > $one) { $one += 8 - length $row[1]; $two = length $row[1]; } sprintf "%-${one}s %${two}s %s\n", @row; } sub pad { my($str, $len, $left) = @_; my $howmany = $len - length($str); return $str if $howmany <= 0; my $pad = " " x $howmany; return $left ? "$pad$str" : "$str$pad"; } 1; Carton-v1.0.28/lib/Carton/Mirror.pm000644 000765 000024 00000000526 12720763413 017774 0ustar00miyagawastaff000000 000000 package Carton::Mirror; use strict; use Class::Tiny qw( url ); our $DefaultMirror = 'http://cpan.metacpan.org/'; sub BUILDARGS { my($class, $url) = @_; return { url => $url }; } sub default { my $class = shift; $class->new($DefaultMirror); } sub is_default { my $self = shift; $self->url eq $DefaultMirror; } 1; Carton-v1.0.28/lib/Carton/Package.pm000644 000765 000024 00000000470 12720763413 020053 0ustar00miyagawastaff000000 000000 package Carton::Package; use strict; use Class::Tiny qw( name version pathname ); sub BUILDARGS { my($class, @args) = @_; return { name => $args[0], version => $args[1], pathname => $args[2] }; } sub version_format { my $self = shift; defined $self->version ? $self->version : 'undef'; } 1; Carton-v1.0.28/lib/Carton/Packer.pm000644 000765 000024 00000004436 12720763413 017733 0ustar00miyagawastaff000000 000000 package Carton::Packer; use Class::Tiny; use warnings NONFATAL => 'all'; use App::FatPacker; use File::pushd (); use Path::Tiny (); use CPAN::Meta (); use File::Find (); sub fatpack_carton { my($self, $dir) = @_; my $temp = Path::Tiny->tempdir; my $pushd = File::pushd::pushd $temp; my $file = $temp->child('carton.pre.pl'); $file->spew(<<'EOF'); #!/usr/bin/env perl use strict; use 5.008001; use Carton::CLI; $Carton::Fatpacked = 1; exit Carton::CLI->new->run(@ARGV); EOF my $fatpacked = $self->do_fatpack($file); my $executable = $dir->child('carton'); warn "Bundling $executable\n"; $dir->mkpath; $executable->spew($fatpacked); chmod 0755, $executable; } sub do_fatpack { my($self, $file) = @_; my $packer = App::FatPacker->new; my @modules = split /\r?\n/, $packer->trace(args => [$file], use => $self->required_modules); my @packlists = $packer->packlists_containing(\@modules); $packer->packlists_to_tree(Path::Tiny->new('fatlib')->absolute, \@packlists); my $fatpacked = do { local $SIG{__WARN__} = sub {}; $packer->fatpack_file($file); }; # HACK: File::Spec bundled into arch in < 5.16, but is loadable as pure-perl use Config; $fatpacked =~ s/\$fatpacked\{"$Config{archname}\/(Cwd|File)/\$fatpacked{"$1/g; $fatpacked; } sub required_modules { my($self, $packer) = @_; my $meta = $self->installed_meta('Carton') or die "Couldn't find install metadata for Carton"; my %excludes = ( perl => 1, 'ExtUtils::MakeMaker' => 1, 'Module::Build' => 1, ); my @requirements = grep !$excludes{$_}, $meta->effective_prereqs->requirements_for('runtime', 'requires')->required_modules; return \@requirements; } sub installed_meta { my($self, $dist) = @_; my @meta; my $finder = sub { if (m!\b$dist-.*[\\/]MYMETA.json!) { my $meta = CPAN::Meta->load_file($_); push @meta, $meta if $meta->name eq $dist; } }; my @meta_dirs = grep -d, map "$_/.meta", @INC; File::Find::find({ wanted => $finder, no_chdir => 1 }, @meta_dirs) if @meta_dirs; # return the latest version @meta = sort { version->new($b->version) cmp version->new($a->version) } @meta; return $meta[0]; } 1; Carton-v1.0.28/lib/Carton/Snapshot/000755 000765 000024 00000000000 12720763413 017760 5ustar00miyagawastaff000000 000000 Carton-v1.0.28/lib/Carton/Snapshot.pm000644 000765 000024 00000010644 12720763413 020323 0ustar00miyagawastaff000000 000000 package Carton::Snapshot; use strict; use Config; use Carton::Dist; use Carton::Dist::Core; use Carton::Error; use Carton::Package; use Carton::Index; use Carton::Util; use Carton::Snapshot::Emitter; use Carton::Snapshot::Parser; use CPAN::Meta; use CPAN::Meta::Requirements; use File::Find (); use Try::Tiny; use Path::Tiny (); use Module::CoreList; use constant CARTON_SNAPSHOT_VERSION => '1.0'; use subs 'path'; use Class::Tiny { path => undef, version => sub { CARTON_SNAPSHOT_VERSION }, loaded => undef, _distributions => sub { +[] }, }; sub BUILD { my $self = shift; $self->path( $self->{path} ); } sub path { my $self = shift; if (@_) { $self->{path} = Path::Tiny->new($_[0]); } else { $self->{path}; } } sub load_if_exists { my $self = shift; $self->load if $self->path->is_file; } sub load { my $self = shift; return 1 if $self->loaded; if ($self->path->is_file) { my $parser = Carton::Snapshot::Parser->new; $parser->parse($self->path->slurp_utf8, $self); $self->loaded(1); return 1; } else { Carton::Error::SnapshotNotFound->throw( error => "Can't find cpanfile.snapshot: Run `carton install` to build the snapshot file.", path => $self->path, ); } } sub save { my $self = shift; $self->path->spew_utf8( Carton::Snapshot::Emitter->new->emit($self) ); } sub find { my($self, $module) = @_; (grep $_->provides_module($module), $self->distributions)[0]; } sub find_or_core { my($self, $module) = @_; $self->find($module) || $self->find_in_core($module); } sub find_in_core { my($self, $module) = @_; if (exists $Module::CoreList::version{$]}{$module}) { my $version = $Module::CoreList::version{$]}{$module}; # maybe undef return Carton::Dist::Core->new(name => $module, module_version => $version); } return; } sub index { my $self = shift; my $index = Carton::Index->new; for my $package ($self->packages) { $index->add_package($package); } return $index; } sub distributions { @{$_[0]->_distributions}; } sub add_distribution { my($self, $dist) = @_; push @{$self->_distributions}, $dist; } sub packages { my $self = shift; my @packages; for my $dist ($self->distributions) { while (my($package, $provides) = each %{$dist->provides}) { # TODO what if duplicates? push @packages, Carton::Package->new($package, $provides->{version}, $dist->pathname); } } return @packages; } sub write_index { my($self, $file) = @_; open my $fh, ">", $file or die $!; $self->index->write($fh); } sub find_installs { my($self, $path, $reqs) = @_; my $libdir = "$path/lib/perl5/$Config{archname}/.meta"; return {} unless -e $libdir; my @installs; my $wanted = sub { if ($_ eq 'install.json') { push @installs, [ $File::Find::name, "$File::Find::dir/MYMETA.json" ]; } }; File::Find::find($wanted, $libdir); my %installs; my $accepts = sub { my $module = shift; return 0 unless $reqs->accepts_module($module->{name}, $module->{provides}{$module->{name}}{version}); if (my $exist = $installs{$module->{name}}) { my $old_ver = version::->new($exist->{provides}{$module->{name}}{version}); my $new_ver = version::->new($module->{provides}{$module->{name}}{version}); return $new_ver >= $old_ver; } else { return 1; } }; for my $file (@installs) { my $module = Carton::Util::load_json($file->[0]); my $prereqs = -f $file->[1] ? CPAN::Meta->load_file($file->[1])->effective_prereqs : CPAN::Meta::Prereqs->new; my $reqs = CPAN::Meta::Requirements->new; $reqs->add_requirements($prereqs->requirements_for($_, 'requires')) for qw( configure build runtime ); if ($accepts->($module)) { $installs{$module->{name}} = Carton::Dist->new( name => $module->{dist}, pathname => $module->{pathname}, provides => $module->{provides}, version => $module->{version}, requirements => $reqs, ); } } my @new_dists; for my $module (sort keys %installs) { push @new_dists, $installs{$module}; } $self->_distributions(\@new_dists); } 1; Carton-v1.0.28/lib/Carton/Tree.pm000644 000765 000024 00000003204 12720763413 017415 0ustar00miyagawastaff000000 000000 package Carton::Tree; use strict; use Carton::Dependency; use Class::Tiny qw( cpanfile snapshot ); use constant STOP => -1; sub walk_down { my($self, $cb) = @_; my $dumper; $dumper = sub { my($dependency, $reqs, $level, $parent) = @_; my $ret = $cb->($dependency, $reqs, $level); return if $ret && $ret == STOP; local $parent->{$dependency->distname} = 1 if $dependency; for my $module (sort $reqs->required_modules) { my $dependency = $self->dependency_for($module, $reqs); if ($dependency->dist) { next if $parent->{$dependency->distname}; $dumper->($dependency, $dependency->requirements, $level + 1, $parent); } else { # no dist found in lock } } }; $dumper->(undef, $self->cpanfile->requirements, 0, {}); undef $dumper; } sub dependency_for { my($self, $module, $reqs) = @_; my $requirement = $reqs->requirements_for_module($module); my $dep = Carton::Dependency->new; $dep->module($module); $dep->requirement($requirement); if (my $dist = $self->snapshot->find_or_core($module)) { $dep->dist($dist); } return $dep; } sub merged_requirements { my $self = shift; my $merged_reqs = CPAN::Meta::Requirements->new; my %seen; $self->walk_down(sub { my($dependency, $reqs, $level) = @_; return Carton::Tree::STOP if $dependency && $seen{$dependency->distname}++; $merged_reqs->add_requirements($reqs); }); $merged_reqs->clear_requirement('perl'); $merged_reqs->finalize; $merged_reqs; } 1; Carton-v1.0.28/lib/Carton/Util.pm000644 000765 000024 00000000751 12720763413 017437 0ustar00miyagawastaff000000 000000 package Carton::Util; use strict; use warnings; sub load_json { my $file = shift; open my $fh, "<", $file or die "$file: $!"; from_json(join '', <$fh>); } sub dump_json { my($data, $file) = @_; open my $fh, ">", $file or die "$file: $!"; binmode $fh; print $fh to_json($data); } sub from_json { require JSON; JSON::decode_json(@_); } sub to_json { my($data) = @_; require JSON; JSON->new->utf8->pretty->canonical->encode($data); } 1; Carton-v1.0.28/lib/Carton/Snapshot/Emitter.pm000644 000765 000024 00000001642 12720763413 021732 0ustar00miyagawastaff000000 000000 package Carton::Snapshot::Emitter; use Class::Tiny; use warnings NONFATAL => 'all'; sub emit { my($self, $snapshot) = @_; my $data = ''; $data .= "# carton snapshot format: version @{[$snapshot->version]}\n"; $data .= "DISTRIBUTIONS\n"; for my $dist (sort { $a->name cmp $b->name } $snapshot->distributions) { $data .= " @{[$dist->name]}\n"; $data .= " pathname: @{[$dist->pathname]}\n"; $data .= " provides:\n"; for my $package (sort keys %{$dist->provides}) { my $version = $dist->provides->{$package}{version}; $version = 'undef' unless defined $version; $data .= " $package $version\n"; } $data .= " requirements:\n"; for my $module (sort $dist->required_modules) { $data .= " $module @{[ $dist->requirements_for_module($module) || '0' ]}\n"; } } $data; } 1; Carton-v1.0.28/lib/Carton/Snapshot/Parser.pm000644 000765 000024 00000006353 12720763413 021561 0ustar00miyagawastaff000000 000000 package Carton::Snapshot::Parser; use Class::Tiny; use warnings NONFATAL => 'all'; use Carton::Dist; use Carton::Error; my $machine = { init => [ { re => qr/^\# carton snapshot format: version (1\.0)/, code => sub { my($stash, $snapshot, $ver) = @_; $snapshot->version($ver); }, goto => 'section', }, # TODO support pasing error and version mismatch etc. ], section => [ { re => qr/^DISTRIBUTIONS$/, goto => 'dists', }, { re => qr/^__EOF__$/, done => 1, }, ], dists => [ { re => qr/^ (\S+)$/, code => sub { $_[0]->{dist} = Carton::Dist->new(name => $1) }, goto => 'distmeta', }, { re => qr/^\S/, goto => 'section', redo => 1, }, ], distmeta => [ { re => qr/^ pathname: (.*)$/, code => sub { $_[0]->{dist}->pathname($1) }, }, { re => qr/^\s{4}provides:$/, code => sub { $_[0]->{property} = 'provides' }, goto => 'properties', }, { re => qr/^\s{4}requirements:$/, code => sub { $_[0]->{property} = 'requirements'; }, goto => 'properties', }, { re => qr/^\s{0,2}\S/, code => sub { my($stash, $snapshot) = @_; $snapshot->add_distribution($stash->{dist}); %$stash = (); # clear }, goto => 'dists', redo => 1, }, ], properties => [ { re => qr/^\s{6}([0-9A-Za-z_:]+) ([v0-9\._,=\!<>\s]+|undef)/, code => sub { my($stash, $snapshot, $module, $version) = @_; if ($stash->{property} eq 'provides') { $stash->{dist}->provides->{$module} = { version => $version }; } else { $stash->{dist}->add_string_requirement($module, $version); } }, }, { re => qr/^\s{0,4}\S/, goto => 'distmeta', redo => 1, }, ], }; sub parse { my($self, $data, $snapshot) = @_; my @lines = split /\r?\n/, $data; my $state = $machine->{init}; my $stash = {}; LINE: for my $line (@lines, '__EOF__') { last LINE unless @$state; STATE: { for my $trans (@{$state}) { if (my @match = $line =~ $trans->{re}) { if (my $code = $trans->{code}) { $code->($stash, $snapshot, @match); } if (my $goto = $trans->{goto}) { $state = $machine->{$goto}; if ($trans->{redo}) { redo STATE; } else { next LINE; } } last STATE; } } Carton::Error::SnapshotParseError->throw(error => "Could not parse snapshot file: $line"); } } } 1; Carton-v1.0.28/lib/Carton/Doc/Bundle.pod000644 000765 000024 00000001040 12720763413 020576 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Bundle - Bundle cached tarballs in vendor/cache =head1 SYNOPSIS carton bundle =head1 DESCRIPTION This command bundles cached tarballs into C directory. These tarballs have been cached in C while resolving dependencies in the snapshot file.snapshot. Bundled modules can be committed to a version control system, or transferred to another host with scp/rsync etc. to use with C. See also C that generates C executable in C. Carton-v1.0.28/lib/Carton/Doc/Check.pod000644 000765 000024 00000001170 12720763413 020406 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Check - Check if your cpanfile and local environment are in sync =head1 SYNOPSIS carton check =head1 DESCRIPTION This command checks the consistency between your C, C and the local environment. =head2 MISSING MODULES If one or more of the modules specified in your I are not found in your snapshot, C will warn you about this: $ carton check Following dependencies are not satisfied. JSON has version 2.51. Needs 2.52 Run `carton install` to install them. You can run C again to reinstall these missing dependencies. Carton-v1.0.28/lib/Carton/Doc/Exec.pod000644 000765 000024 00000001207 12720763413 020256 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Exec - execute your script in a carton local environment =head1 SYNOPSIS carton exec perl myscript.pl =head1 DESCRIPTION This command allows you to run your script in an isolated carton local environment, which means the perl 5 library path C<@INC> are the only ones from perl's core library path, carton's library path (i.e. C) and the current directory. This is useful to make sure your scripts and application use the exact same versions of the modules in your library path, and are not using any of the modules you accidentally installed into your system perl or perlbrew's site library path. Carton-v1.0.28/lib/Carton/Doc/FAQ.pod000644 000765 000024 00000011704 12720763413 020004 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::FAQ - Frequently Asked Questions =head1 QUESTIONS =head2 It looks useful, but what is the use case of this tool? The particular problem that carton is trying to address is this: You develop a Perl-based application, possibly but not limited to webapps, with dozens of CPAN module dependencies. You install these modules on your development machine, and describe these dependencies in your I. Now you get a production environment, either on PaaS provider or some VPS, you install the dependencies using C and it will pull all the latest releases from CPAN as of today and everything just works. A few weeks later, your application becomes more popular, and you think you need another machine to serve more requests. You set up another machine with vanilla perl installation and install the dependencies the same way. That will pull the I releases from CPAN I, rather than the same as what you have today. And that is the problem. It's not likely that everything just breaks one day, but there's always a chance that one of the dependencies breaks an API compatibility, or just uploaded a buggy version to CPAN on that particular day. Carton allows you to I these dependencies into a version controlled system, so that every time you deploy from a checkout, it is guaranteed that all the same versions are installed into the local environment. =head2 How is this different from Pinto or CPAN::Mini::Inject? carton definitely shares the goal with these private CPAN repository management tool. But the main difference is that rather than creating an actual CPAN-like repository that works with any CPAN clients, Carton provides a way to install specific versions of distributions from CPAN, or any CPAN-like mirrors (as well as git repositories in the future version of Carton). Existing tools are designed to work I CPAN clients such as L or L, and have accomplished that by working around the CPAN mirror structure. carton I does the same thing, but its user interface is centered around the installer, by implementing a wrapper for L, so you can use the same commands in the development mode and deployment mode. Carton automatically maintains the L file, which is meant to be version controlled, inside your application directory. You don't need a separate database, a directory or a web server to maintain tarballs outside your application. The I file can always be generated with C command, and C on another machine can use the version in the snapshot. =head2 I already use Pinto to create DarkPAN mirror. Can I use Carton with this? Yes, by specifying Pinto mirror as your Carton mirror, you can take a snapshot of your dependencies including your private modules on Pinto, or whatever DarkPAN mirror. =head2 I'm already using perlbrew and local::lib. Can I use carton with this? If you're using L already with L perl, possibly with the new C command, that's great! There are multiple benefits over using L and L for development and use L for deployment. The best practice and workflow to get your perl environment as clean as possible with lots of modules installed for quick development would be this: =over =item * Install fresh perl using perlbrew. The version must be the same against the version you'll run on the production environment. =item * Once the installation is done, use C command to create a new local lib environment (let's call it I) and always use the library as a default environment. Install as many modules as you would like into the I library path. This ensures to have a vanilla C library path as clean as possible. =item * When you build a new project that you want to manage dependencies via Carton, turn off the I local::lib and create a new one, like I. Install L and all of its dependencies to the I local::lib path. Then run C like you normally do. Because I and I are isolated, the modules you installed into I doesn't affect the process when carton builds the dependency tree for your new project at all. This could often be critical when you have a conditional dependency in your tree, like L. =back =head2 I'm using perlbrew, but C<< carton install >> uses system perl, how to fix? The issue is most likelly caused by a inital bad install of C or C or both, that ended up with a shebang line pointed to the (wrong) system perl. =over 4 =item Re-install Carton on you perlbrew environment Run C<< cpanm -f Carton >>. This will force-install Carton, and because your C is now using the correct C, the same will happen with C. =back Make sure the shebang (the first line) of your C script points to the right perl path, rather than C. Carton-v1.0.28/lib/Carton/Doc/Fatpack.pod000644 000765 000024 00000000521 12720763413 020741 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Fatpack - Fatpack carton executable into vendor/bin =head1 SYNOPSIS carton fatpack =head1 DESCRIPTION This command creates a fatpack executable of C in C directory, so that it can be used to bootstrap deployment process, combined with C and C. Carton-v1.0.28/lib/Carton/Doc/Install.pod000644 000765 000024 00000005666 12720763413 021015 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Install - Install the dependencies =head1 SYNOPSIS carton install [--deployment] [--cached] [--path=PATH] [--without develop] =head1 DESCRIPTION Install the dependencies for your application. This command has two modes and the behavior is slightly different. =head2 DEVELOPMENT MODE =over 4 =item carton install If you run C without any arguments and if I exists, carton will scan dependencies from I and install the modules. =back If you run C for the first time (i.e. I does not exist), carton will fetch all the modules specified, resolve dependencies and install all required modules from CPAN. If I file does exist, carton will still try to install modules specified or updated in I, but uses I for the dependency resolution, and then cascades to CPAN. carton will analyze all the dependencies and their version information, and it is saved into I file. It is important to add I file into a version controlled repository and commit the changes as you update your dependencies. =head2 DEPLOYMENT MODE If you specify the C<--deployment> command line option or the I exists, carton will only use the dependencies specified in the I instead of resolving dependencies. =head1 OPTIONS =over 4 =item --deployment Force the deployment mode. See L above. =item --cached Locate distribution tarballs in C rather than fetching them from CPAN mirrors. This requires you to run C prior to the deployment and commit or sync the content of C directory to the other host you run C on. =item --cpanfile Specify the alternate path for cpanfile. By default, C will look for the file C in the current directory, then upwards till the root directory, in case the command runs from a sub directory. Carton assumes the directory where your cpanfile (or altenate path) exists as a project root directory, and will look for the snapshot file as well as install directory (C) and C relative to it. =item --path Specify the path to install modules to. Defaults to I in the directory relative to where C is. B: this option, as of version 1.0, is not preserved across multiple runs of C or other commands such as C or C. You can choose to set the path in C environment variable to persist it across commands. =item --without By default, C will install all the phases for dependencies, including C. You can specify phases or features to exclude, in the comma separated list. carton install --deployment --without develop B: C<--without> for the initial installation (without cpanfile.snapshot) is not supported at this moment. =back Carton-v1.0.28/lib/Carton/Doc/List.pod000644 000765 000024 00000000730 12720763413 020305 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::List - List dependencies tracked in the cpanfile.snapshot file =head1 SYNOPSIS carton list =head1 DESCRIPTION List the dependencies and version information tracked in the I file. This command by default displays the name of the distribution (e.g. I) in a flat list. =head1 OPTIONS =over 4 =item --distfile Displays the list of distributions in a distfile format (i.e. C) =back Carton-v1.0.28/lib/Carton/Doc/Show.pod000644 000765 000024 00000000301 12720763413 020304 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Show - Show the module information =head1 SYNOPSIS carton show Module =head1 DESCRIPTION Displays the information about modules, distribution and its versions. Carton-v1.0.28/lib/Carton/Doc/Tree.pod000644 000765 000024 00000000305 12720763413 020267 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Tree - Show the tree of dependency graph =head1 SYNOPSIS carton tree =head1 DESCRIPTION Displays the tree representation of dependency graph for your application. Carton-v1.0.28/lib/Carton/Doc/Update.pod000644 000765 000024 00000002306 12720763413 020615 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Update - Update the dependencies =head1 SYNOPSIS carton update [module] =head1 DESCRIPTION Update the dependencies version for your application. Carton is designed to update your dependency in a conservative way, meaning that it doesn't update modules that aren't explicitly required to. C is a command to explicitly update one or all of modules in your cpanfile to the latest available that satisfies the requirements in cpanfile. =head1 EXAMPLE Suppose you have a cpanfile with: requires 'DBI', '1.600'; requires 'Plack', '== 1.0011'; and then run C to get DBI 1.610 (the latest at that time) and Plack 1.0011 (as specified in the requirement). A few weeks later, DBI and Plack have been updated a couple of times. Running C I update the versions, because the installed versions satisfy the requirements in C. Running C will update DBI to the latest version, say 1.611, because the version still satisfies the requirement. However, it won't update Plack's version, since whatever latest version on CPAN will not satisfy the Plack's requirement C<== 1.0011> because it wants an exact version. Carton-v1.0.28/lib/Carton/Doc/Upgrading.pod000644 000765 000024 00000002161 12720763413 021312 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Upgrading - Upgrading document =head1 UPGRADING Carton adds, changes and deprecates some features between major releases in backward incompatible ways. Here's the list of major changes between versions. See C file for more details. =head2 v0.9 to v1.0 =over 4 =item * C is deprecated. You must pass the optional include path to perl interpreter in the normal way, like: carton exec perl -Ilib myscript Or make your script to take its own C<-I> option, like many command line launcher does (i.e. plackup, prove) carton exec plackup -Ilib myapp.psgi =item * C is now C. Its name and file format has been changed. There's no automatic migration, but you can do: # run with Carton v0.9.64 > carton install # upgrade to Carton v1.0 > cpanm Carton > carton install > git add cpanfile.snapshot > git rm carton.lock This process will most likely preserve modules in your local library. =item * cpanfile is now a requirement, and extracting requirements from build files (C, C) is not supported. =back Carton-v1.0.28/lib/Carton/Doc/Version.pod000644 000765 000024 00000000250 12720763413 021014 0ustar00miyagawastaff000000 000000 =head1 NAME Carton::Doc::Version - Display version =head1 SYNOPSIS carton version =head1 DESCRIPTION This command displays the current version number of carton. Carton-v1.0.28/lib/Carton/Dist/Core.pm000644 000765 000024 00000000507 12720763413 020314 0ustar00miyagawastaff000000 000000 package Carton::Dist::Core; use strict; use parent 'Carton::Dist'; use Class::Tiny qw( module_version ); sub BUILDARGS { my($class, %args) = @_; # TODO represent dual-life $args{name} =~ s/::/-/g; \%args; } sub is_core { 1 } sub version_for { my($self, $module) = @_; $self->module_version; } 1;