PaxHeader/Code-TidyAll-0.18000775 777777 777777 00000000213 12217370452 015636 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705250 19 SCHILY.nlink=16 Code-TidyAll-0.18/000775 €ˆž«€q{Ì00000000000 12217370452 014671 5ustar00jonswart000000 000000 Code-TidyAll-0.18/PaxHeader/bin000775 777777 777777 00000000212 12217370452 016405 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705253 18 SCHILY.nlink=3 Code-TidyAll-0.18/bin/000775 €ˆž«€q{Ì00000000000 12217370452 015441 5ustar00jonswart000000 000000 Code-TidyAll-0.18/PaxHeader/Changes000644 777777 777777 00000000212 12217370452 017200 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705251 18 SCHILY.nlink=1 Code-TidyAll-0.18/Changes000644 €ˆž«€q{Ì00000012020 12217370452 016155 0ustar00jonswart000000 000000 Revision history for Code-TidyAll ** denotes an incompatible change 0.18 Sep 21, 2013 * Fixes - Fix Test::Code::TidyAll::tidyall_ok - https://github.com/jonswar/perl-code-tidyall/issues/12 (Adam Taylor) - Fix JSBeautify plugin as js-beautify no longer respects --replace 0.17 Mar 11, 2013 * Improvements - ** Rename API method process_files to more accurate process_paths * Fixes - Fix recursive processing of directories (Mark Risman) - Improve git precommit setup script - https://github.com/jonswar/perl-code-tidyall/pull/10 (Olaf Anders) 0.16 Oct 22, 2012 * Plugins - Add phpcs plugin (Joseph Crotty) - Add cssunminifier plugin - Add SortLines plugin, for one-entry-per-line files like .gitignore 0.15 Oct 11, 2012 * Fixes - Fix test_dirs test to not rely on file ordering 0.14 Oct 10, 2012 * Improvements - Allow a plugin to be listed multiple times in config with different configuration - Specify order that plugins run (tidiers before validators, then alpha) and document that they are applied atomically - Add etc/editors/tidyall.vim for Vim (Justin Devuyst) - Add -r/--recursive flag to process directories recursively - In -p/--pipe mode, mirror input to output in case of error (Justin Devuyst) - Fix -l/--list handling of local files - Add --version option - Make git prereceive hook more modular, so it can be combined with other checks 0.13 Sep 30, 2012 * Fixes - Adjust MasonTidy plugin for new API - Remove Util.t containing only author-only tests 0.12 Sep 27, 2012 * Plugins - Add podspell plugin (POD spell checker) * Improvements - Add --iterations flag to run tidier transforms multiple times - Allow .tidyallrc as alternative to tidyall.ini - Allow git prereceive hook to be bypassed by pushing an identical set of commits several consecutive times (allow_repeated_push) - Add handcrafted usage w/summary of options, instead of Pod::Usage 0.11 Sep 21, 2012 * Improvements - Allow multiple select and ignore patterns, separated by whitespace or on separate lines - Add -l/--list flag to show which plugins match which files - Add conf_name parameter to specify name other than tidyall.ini - Redirect stdout to stderr with -p/--pipe, so that stdout is dedicated to the tidied content - In tidyall.el, hide error buffer on successful tidy * Fixes - Handle argv/config errors correctly in various plugins - Eliminate double-printed error with -p/--pipe - Allow relative paths to -p/--pipe 0.10 Sep 12, 2012 * Plugins - Add masontidy plugin (Mason component tidier) - Add jslint plugin (javascript validator) 0.09 Sep 11, 2012 * Fixes - Remove use of ex-dependency Hash::MoreUtils from bin/tidyall (Jason Wieland) - Add IPC::System::Simple and Pod::Usage to deps (Jason Wieland) 0.08 Sep 10, 2012 * Plugins - Add js-beautify plugin (javascript tidier) - Add jshint plugin (javascript validator) - Add podchecker plugin * Improvements - Add -p/--pipe flag to read from STDIN and write to STDOUT - Allow tidyall.el to work in narrowed regions - Make plugins into Moo classes, pass configuration as attributes * Fixes - Remove unused SVN::Look - perl-code-tidyall/pull/1 (Pedro Melo) - Filter just files from git status in Code::TidyAll::Git::Precommit (Pedro Melo) 0.07 Sep 5, 2012 * Improvements - Add git pre-receive hook (Code::TidyAll::Git::Prereceive) * Fixes - Show file paths with errors in quiet mode 0.06 Sep 3, 2012 * Improvements - Add -g/--git flag and git pre-commit hook (Code::TidyAll::Git::Precommit) * Fixes - Omit directories from svn_uncommitted_files (--svn) 0.05 Aug 21, 2012 * Improvements - Add etc/editors/tidyall.el for Emacs - Only print 'no plugins apply' warning in verbose mode 0.04 Aug 14, 2012 * Fixes - Add back missing plugins - Fix --check-only flag * Improvements - Add -s/--svn flag - Add emergency_comment_prefix ("NO TIDYALL") to svn precommit hook 0.03 Jul 24, 2012 * Improvements - Add svn precommit hook (Code::TidyAll::SVN::Precommit) - Add preprocess_source and postprocess_source to plugins - Add only_modes and except_modes configuration for plugins - Add Code::TidyAll::process_source(), for processing a string instead of a file - When only specified files are being processed, don't scan the whole hierarchy - Add -I flag to tidyall * Implementation - Switch to Moo - Add separate new_from_conf_file constructor, for cleaner separation of cases 0.02 Jul 3, 2012 * Improvements - Add Test::Code::TidyAll, to test that a project is tidied - Add prefilter and postfilter params, to be applied to code before and after processing - Add --check-only option to check but not tidy - Add --mode option and modes config entry, to activate only a subset of plugins in config - Add --output-suffix to write file to a different destination - Add --quiet option to suppress most output - Add --tidyall-class option to specify a different Code::TidyAll subclass * Documentation - Document how to create new plugins in Code::Tidy::Plugin 0.01 Jun 17, 2012 - Initial version Code-TidyAll-0.18/PaxHeader/etc000775 777777 777777 00000000212 12217370452 016410 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705255 18 SCHILY.nlink=3 Code-TidyAll-0.18/etc/000775 €ˆž«€q{Ì00000000000 12217370452 015444 5ustar00jonswart000000 000000 Code-TidyAll-0.18/PaxHeader/INSTALL000644 777777 777777 00000000212 12217370452 016736 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705354 18 SCHILY.nlink=1 Code-TidyAll-0.18/INSTALL000644 €ˆž«€q{Ì00000001672 12217370452 015726 0ustar00jonswart000000 000000 This is the Perl distribution Code-TidyAll. Installing Code-TidyAll is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm Code::TidyAll If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S Code::TidyAll ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan Code::TidyAll ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, then build it: % perl Makefile.PL % make && make test Then install it: % make install If you are installing into a system-wide directory, you may need to run: % sudo make install ## Documentation Code-TidyAll documentation is available as POD. You can run perldoc from a shell to read the documentation: % perldoc Code::TidyAll Code-TidyAll-0.18/PaxHeader/lib000775 777777 777777 00000000212 12217370452 016403 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705259 18 SCHILY.nlink=5 Code-TidyAll-0.18/lib/000775 €ˆž«€q{Ì00000000000 12217370452 015437 5ustar00jonswart000000 000000 Code-TidyAll-0.18/PaxHeader/LICENSE000644 777777 777777 00000000212 12217370452 016712 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705349 18 SCHILY.nlink=1 Code-TidyAll-0.18/LICENSE000644 €ˆž«€q{Ì00000043664 12217370452 015711 0ustar00jonswart000000 000000 This software is copyright (c) 2011 by Jonathan Swartz. 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 Jonathan Swartz. 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, Suite 500, Boston, MA 02110-1335 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 Jonathan Swartz. 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 Code-TidyAll-0.18/PaxHeader/Makefile.PL000644 777777 777777 00000000212 12217370452 017657 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705353 18 SCHILY.nlink=1 Code-TidyAll-0.18/Makefile.PL000644 €ˆž«€q{Ì00000003601 12217370452 016641 0ustar00jonswart000000 000000 use strict; use warnings; use ExtUtils::MakeMaker 6.30; my %WriteMakefileArgs = ( "ABSTRACT" => "Tidy and validate code in many ways at once", "AUTHOR" => "Jonathan Swartz ", "BUILD_REQUIRES" => {}, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "6.30" }, "DISTNAME" => "Code-TidyAll", "EXE_FILES" => [ "bin/tidyall" ], "LICENSE" => "perl", "NAME" => "Code::TidyAll", "PREREQ_PM" => { "Capture::Tiny" => "0.12", "Config::INI::Reader" => 0, "Date::Format" => 0, "Digest::SHA1" => 0, "File::Basename" => 0, "File::Find" => 0, "File::Path" => 0, "File::Temp" => 0, "File::Zglob" => 0, "Getopt::Long" => 0, "Guard" => 0, "IPC::Run3" => 0, "IPC::System::Simple" => "0.15", "List::MoreUtils" => 0, "Log::Any" => 0, "Moo" => "0.0091010", "Scalar::Util" => 0, "Text::ParseWords" => 0, "Time::Duration::Parse" => 0, "Try::Tiny" => 0 }, "TEST_REQUIRES" => { "Test::Class::Most" => 0 }, "VERSION" => "0.18", "test" => { "TESTS" => "t/*.t" } ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { my $tr = delete $WriteMakefileArgs{TEST_REQUIRES}; my $br = $WriteMakefileArgs{BUILD_REQUIRES}; for my $mod ( keys %$tr ) { if ( exists $br->{$mod} ) { $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod}; } else { $br->{$mod} = $tr->{$mod}; } } } unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) { my $br = delete $WriteMakefileArgs{BUILD_REQUIRES}; my $pp = $WriteMakefileArgs{PREREQ_PM}; for my $mod ( keys %$br ) { if ( exists $pp->{$mod} ) { $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod}; } else { $pp->{$mod} = $br->{$mod}; } } } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Code-TidyAll-0.18/PaxHeader/MANIFEST000644 777777 777777 00000000212 12217370452 017036 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705350 18 SCHILY.nlink=1 Code-TidyAll-0.18/MANIFEST000644 €ˆž«€q{Ì00000004426 12217370452 016026 0ustar00jonswart000000 000000 Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL bin/tidyall etc/editors/tidyall.el etc/editors/tidyall.vim lib/Code/TidyAll.pm lib/Code/TidyAll/Cache.pm lib/Code/TidyAll/Config/INI/Reader.pm lib/Code/TidyAll/Git/Precommit.pm lib/Code/TidyAll/Git/Prereceive.pm lib/Code/TidyAll/Git/Util.pm lib/Code/TidyAll/Plugin.pm lib/Code/TidyAll/Plugin/CSSUnminifier.pm lib/Code/TidyAll/Plugin/JSBeautify.pm lib/Code/TidyAll/Plugin/JSHint.pm lib/Code/TidyAll/Plugin/JSLint.pm lib/Code/TidyAll/Plugin/MasonTidy.pm lib/Code/TidyAll/Plugin/PHPCodeSniffer.pm lib/Code/TidyAll/Plugin/PerlCritic.pm lib/Code/TidyAll/Plugin/PerlTidy.pm lib/Code/TidyAll/Plugin/PodChecker.pm lib/Code/TidyAll/Plugin/PodSpell.pm lib/Code/TidyAll/Plugin/PodTidy.pm lib/Code/TidyAll/Plugin/SortLines.pm lib/Code/TidyAll/Result.pm lib/Code/TidyAll/SVN/Precommit.pm lib/Code/TidyAll/SVN/Util.pm lib/Code/TidyAll/Test/Class.pm lib/Code/TidyAll/Test/Plugin/AToZ.pm lib/Code/TidyAll/Test/Plugin/CheckUpper.pm lib/Code/TidyAll/Test/Plugin/RepeatFoo.pm lib/Code/TidyAll/Test/Plugin/ReverseFoo.pm lib/Code/TidyAll/Test/Plugin/UpperText.pm lib/Code/TidyAll/Util.pm lib/Code/TidyAll/Util/Zglob.pm lib/Code/TidyAll/t/Basic.pm lib/Code/TidyAll/t/Conf.pm lib/Code/TidyAll/t/Git.pm lib/Code/TidyAll/t/Plugin.pm lib/Code/TidyAll/t/Plugin/CSSUnminifier.pm lib/Code/TidyAll/t/Plugin/JSBeautify.pm lib/Code/TidyAll/t/Plugin/JSHint.pm lib/Code/TidyAll/t/Plugin/JSLint.pm lib/Code/TidyAll/t/Plugin/MasonTidy.pm lib/Code/TidyAll/t/Plugin/PHPCodeSniffer.pm lib/Code/TidyAll/t/Plugin/PerlCritic.pm lib/Code/TidyAll/t/Plugin/PerlTidy.pm lib/Code/TidyAll/t/Plugin/PodChecker.pm lib/Code/TidyAll/t/Plugin/PodSpell.pm lib/Code/TidyAll/t/Plugin/PodTidy.pm lib/Code/TidyAll/t/Plugin/SortLines.pm lib/Code/TidyAll/t/SVN.pm lib/Code/TidyAll/t/Util.pm lib/Code/TidyAll/t/Zglob.pm lib/Pod/Weaver/Section/SeeAlsoCodeTidyAll.pm lib/Test/Code/TidyAll.pm perltidy.LOG t/Basic.t t/Conf.t t/Zglob.t t/author-Git.t t/author-Plugin-CSSUnminifier.t t/author-Plugin-JSBeautify.t t/author-Plugin-JSHint.t t/author-Plugin-JSLint.t t/author-Plugin-MasonTidy.t t/author-Plugin-PerlCritic.t t/author-Plugin-PerlTidy.t t/author-Plugin-PodChecker.t t/author-Plugin-PodSpell.t t/author-Plugin-PodTidy.t t/author-Plugin-SortLines.t t/author-SVN.t t/author-Util.t t/author-tidy-and-critic.t xt/tidyall.t Code-TidyAll-0.18/PaxHeader/META.json000644 777777 777777 00000000212 12217370452 017326 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705351 18 SCHILY.nlink=1 Code-TidyAll-0.18/META.json000644 €ˆž«€q{Ì00000003742 12217370452 016316 0ustar00jonswart000000 000000 { "abstract" : "Tidy and validate code in many ways at once", "author" : [ "Jonathan Swartz " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 4.300034, CPAN::Meta::Converter version 2.131560", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Code-TidyAll", "no_index" : { "directory" : [ "lib/Code/TidyAll/t", "lib/Code/TidyAll/Test" ], "file" : [ "lib/Code/TidyAll/Util.pm" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.30" } }, "runtime" : { "requires" : { "Capture::Tiny" : "0.12", "Config::INI::Reader" : "0", "Date::Format" : "0", "Digest::SHA1" : "0", "File::Basename" : "0", "File::Find" : "0", "File::Path" : "0", "File::Temp" : "0", "File::Zglob" : "0", "Getopt::Long" : "0", "Guard" : "0", "IPC::Run3" : "0", "IPC::System::Simple" : "0.15", "List::MoreUtils" : "0", "Log::Any" : "0", "Moo" : "0.0091010", "Scalar::Util" : "0", "Text::ParseWords" : "0", "Time::Duration::Parse" : "0", "Try::Tiny" : "0" } }, "test" : { "requires" : { "Test::Class::Most" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-code-tidyall@rt.cpan.org", "web" : "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Code-TidyAll" }, "repository" : { "type" : "git", "url" : "git://github.com/jonswar/perl-code-tidyall.git", "web" : "https://github.com/jonswar/perl-code-tidyall" } }, "version" : "0.18" } Code-TidyAll-0.18/PaxHeader/META.yml000644 777777 777777 00000000212 12217370452 017156 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705352 18 SCHILY.nlink=1 Code-TidyAll-0.18/META.yml000644 €ˆž«€q{Ì00000002062 12217370452 016140 0ustar00jonswart000000 000000 --- abstract: 'Tidy and validate code in many ways at once' author: - 'Jonathan Swartz ' build_requires: Test::Class::Most: 0 configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 4.300034, CPAN::Meta::Converter version 2.131560' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Code-TidyAll no_index: directory: - lib/Code/TidyAll/t - lib/Code/TidyAll/Test file: - lib/Code/TidyAll/Util.pm requires: Capture::Tiny: 0.12 Config::INI::Reader: 0 Date::Format: 0 Digest::SHA1: 0 File::Basename: 0 File::Find: 0 File::Path: 0 File::Temp: 0 File::Zglob: 0 Getopt::Long: 0 Guard: 0 IPC::Run3: 0 IPC::System::Simple: 0.15 List::MoreUtils: 0 Log::Any: 0 Moo: 0.0091010 Scalar::Util: 0 Text::ParseWords: 0 Time::Duration::Parse: 0 Try::Tiny: 0 resources: bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Code-TidyAll repository: git://github.com/jonswar/perl-code-tidyall.git version: 0.18 Code-TidyAll-0.18/PaxHeader/perltidy.LOG000644 777777 777777 00000000212 12217370452 020104 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705252 18 SCHILY.nlink=1 Code-TidyAll-0.18/perltidy.LOG000644 €ˆž«€q{Ì00000001640 12217370452 017067 0ustar00jonswart000000 000000 perltidy version 20121207 log file on a darwin system, OLD_PERL_VERSION=5.012004 Configuration and command line parameters for this run: -noll -l=100 To find error messages search for 'WARNING' with your editor Indentation will be with 4 spaces Line 1 implies starting-indentation-level = 0 The nesting depths in the table below are at the start of the lines. The indicated output line numbers are not always exact. ci = levels of continuation indentation; bk = 1 if in BLOCK, 0 if not. in:out indent c b nesting code + messages; (messages begin with >>>) lines levels i k (code begins with one '.' per indent level) ------ ----- - - -------- ------------------------------------------- L3:3 i0:0 0 1 >>>Last line No indentation disagreement seen No lines exceeded 100 characters Maximum output line length was 34 at line 3 Suggest including 'use warnings;' Suggest including 'use strict;' Code-TidyAll-0.18/PaxHeader/README000664 777777 777777 00000000212 12217370452 016567 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705356 18 SCHILY.nlink=1 Code-TidyAll-0.18/README000664 €ˆž«€q{Ì00000007256 12217370452 015563 0ustar00jonswart000000 000000 NAME Code::TidyAll - Engine for tidyall, your all-in-one code tidier and validator VERSION version 0.18 SYNOPSIS use Code::TidyAll; my $ct = Code::TidyAll->new_from_conf_file( '/path/to/conf/file', ... ); # or my $ct = Code::TidyAll->new( root_dir => '/path/to/root', plugins => { perltidy => { select => 'lib/**/*.(pl|pm)', argv => '-noll -it=2', }, ... } ); # then... $ct->process_paths($file1, $file2); DESCRIPTION This is the engine used by tidyall - read that first to get an overview. You can call this API from your own program instead of executing `tidyall'. CONSTRUCTION Constructor methods new (%params) The regular constructor. Must pass at least *plugins* and *root_dir*. new_with_conf_file ($conf_file, %params) Takes a conf file path, followed optionally by a set of key/value parameters. Reads parameters out of the conf file and combines them with the passed parameters (the latter take precedence), and calls the regular constructor. If the conf file or params defines *tidyall_class*, then that class is constructed instead of `Code::TidyAll'. Constructor parameters plugins Specify a hash of plugins, each of which is itself a hash of options. This is equivalent to what would be parsed out of the sections in the configuration file. backup_ttl check_only data_dir iterations mode no_backups no_cache output_suffix quiet root_dir verbose These options are the same as the equivalent `tidyall' command-line options, replacing dashes with underscore (e.g. the `backup-ttl' option becomes `backup_ttl' here). METHODS process_paths (path, ...) Call process_file on each file; descend recursively into each directory if the `recursive' flag is on. Return a list of Code::TidyAll::Result objects, one for each file. process_file (file) Process the *file*, meaning * Check the cache and return immediately if file has not changed * Apply appropriate matching plugins * Print success or failure result to STDOUT, depending on quiet/verbose settings * Write the cache if enabled * Return a Code::TidyAll::Result object process_source (*source*, *path*) Like process_file, but process the *source* string instead of a file, and do not read from or write to the cache. You must still pass the relative *path* from the root as the second argument, so that we know which plugins to apply. Return a Code::TidyAll::Result object. plugins_for_path (*path*) Given a relative *path* from the root, return a list of Code::TidyAll::Plugin objects that apply to it, or an empty list if no plugins apply. find_conf_file (*conf_names*, *start_dir*) Class method. Start in the *start_dir* and work upwards, looking for one of the *conf_names*. Return the pathname if found or throw an error if not found. find_matched_files Returns a list of sorted files that match at least one plugin in configuration. SEE ALSO Code::TidyAll AUTHOR Jonathan Swartz COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Code-TidyAll-0.18/PaxHeader/t000775 777777 777777 00000000213 12217370452 016101 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705328 19 SCHILY.nlink=20 Code-TidyAll-0.18/t/000775 €ˆž«€q{Ì00000000000 12217370452 015134 5ustar00jonswart000000 000000 Code-TidyAll-0.18/PaxHeader/xt000775 777777 777777 00000000212 12217370452 016270 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705332 18 SCHILY.nlink=3 Code-TidyAll-0.18/xt/000775 €ˆž«€q{Ì00000000000 12217370452 015324 5ustar00jonswart000000 000000 Code-TidyAll-0.18/xt/PaxHeader/tidyall.t000755 777777 777777 00000000212 12217370452 020172 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705333 18 SCHILY.nlink=1 Code-TidyAll-0.18/xt/tidyall.t000755 €ˆž«€q{Ì00000000067 12217370452 017157 0ustar00jonswart000000 000000 #!/usr/bin/perl use Test::Code::TidyAll; tidyall_ok(); Code-TidyAll-0.18/t/PaxHeader/author-Git.t000644 777777 777777 00000000212 12217370452 020360 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705334 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Git.t000644 €ˆž«€q{Ì00000000345 12217370452 017344 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Git; Code::TidyAll::t::Git->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-CSSUnminifier.t000644 777777 777777 00000000212 12217370452 023547 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705335 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-CSSUnminifier.t000644 €ˆž«€q{Ì00000000411 12217370452 022525 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::CSSUnminifier; Code::TidyAll::t::Plugin::CSSUnminifier->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-JSBeautify.t000644 777777 777777 00000000212 12217370452 023076 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705336 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-JSBeautify.t000644 €ˆž«€q{Ì00000000403 12217370452 022055 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::JSBeautify; Code::TidyAll::t::Plugin::JSBeautify->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-JSHint.t000644 777777 777777 00000000212 12217370452 022230 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705337 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-JSHint.t000644 €ˆž«€q{Ì00000000373 12217370452 021215 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::JSHint; Code::TidyAll::t::Plugin::JSHint->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-JSLint.t000644 777777 777777 00000000212 12217370452 022234 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705338 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-JSLint.t000644 €ˆž«€q{Ì00000000373 12217370452 021221 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::JSLint; Code::TidyAll::t::Plugin::JSLint->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-MasonTidy.t000644 777777 777777 00000000212 12217370452 023000 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705339 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-MasonTidy.t000644 €ˆž«€q{Ì00000000401 12217370452 021755 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::MasonTidy; Code::TidyAll::t::Plugin::MasonTidy->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-PerlCritic.t000644 777777 777777 00000000212 12217370452 023131 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705340 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-PerlCritic.t000644 €ˆž«€q{Ì00000000403 12217370452 022110 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::PerlCritic; Code::TidyAll::t::Plugin::PerlCritic->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-PerlTidy.t000644 777777 777777 00000000212 12217370452 022625 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705341 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-PerlTidy.t000644 €ˆž«€q{Ì00000000377 12217370452 021616 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::PerlTidy; Code::TidyAll::t::Plugin::PerlTidy->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-PodChecker.t000644 777777 777777 00000000212 12217370452 023100 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705342 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-PodChecker.t000644 €ˆž«€q{Ì00000000403 12217370452 022057 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::PodChecker; Code::TidyAll::t::Plugin::PodChecker->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-PodSpell.t000644 777777 777777 00000000212 12217370452 022613 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705343 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-PodSpell.t000644 €ˆž«€q{Ì00000000377 12217370452 021604 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::PodSpell; Code::TidyAll::t::Plugin::PodSpell->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-PodTidy.t000644 777777 777777 00000000212 12217370452 022445 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705344 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-PodTidy.t000644 €ˆž«€q{Ì00000000375 12217370452 021434 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::PodTidy; Code::TidyAll::t::Plugin::PodTidy->runtests; Code-TidyAll-0.18/t/PaxHeader/author-Plugin-SortLines.t000644 777777 777777 00000000212 12217370452 023013 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705345 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Plugin-SortLines.t000644 €ˆž«€q{Ì00000000401 12217370452 021770 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Plugin::SortLines; Code::TidyAll::t::Plugin::SortLines->runtests; Code-TidyAll-0.18/t/PaxHeader/author-SVN.t000644 777777 777777 00000000212 12217370452 020303 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705346 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-SVN.t000644 €ˆž«€q{Ì00000000345 12217370452 017267 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::SVN; Code::TidyAll::t::SVN->runtests; Code-TidyAll-0.18/t/PaxHeader/author-tidy-and-critic.t000644 777777 777777 00000000212 12217370452 022621 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705347 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-tidy-and-critic.t000644 €ˆž«€q{Ì00000003624 12217370452 021610 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::Util qw(read_file tempdir_simple write_file); use Code::TidyAll; use File::Basename; use File::Path; use Test::More; use Capture::Tiny qw(capture_merged); my $root_dir = tempdir_simple('Code-TidyAll-XXXX'); sub make { my ( $file, $content ) = @_; $file = "$root_dir/$file"; mkpath( dirname($file), 0, 0775 ); write_file( $file, $content ); } make( "lib/Foo.pm", 'package Foo; use strict; 1; ' ); make( "bin/bar.pl", "#!/usr/bin/perl\n \$d = 5;" ); make( "lib/Foo.pod", "=over\n\n=item a\n\n" . scalar( "Blah " x 25 ) . "\n\n=back\n" ); make( "data/baz.txt", " 34" ); make( ".perlcriticrc", "include = RequireUseStrict" ); my $ct = Code::TidyAll->new( root_dir => $root_dir, plugins => { PerlTidy => { select => '**/*.{pl,pm}' }, PerlCritic => { select => '**/*.{pl,pm}', argv => "--profile $root_dir/.perlcriticrc" }, PodTidy => { select => '**/*.pod' }, } ); my $output; $output = capture_merged { $ct->process_all() }; like( $output, qr/Code before strictures are enabled./ ); is( read_file("$root_dir/lib/Foo.pm"), "package Foo;\nuse strict;\n1;\n" ); is( read_file("$root_dir/lib/Foo.pod"), "=over\n\n=item a\n\n" . join( " ", ("Blah") x 16 ) . "\n" . join( " ", ("Blah") x 9 ) . "\n\n=back\n" ); is( read_file("$root_dir/data/baz.txt"), " 34" ); $output = capture_merged { $ct->process_all() }; like( $output, qr/Code before strictures are enabled./ ); unlike( $output, qr/Foo\.pm/ ); make( "bin/bar.pl", "#!/usr/bin/perl\nuse strict;\n \$d = 5;" ); $output = capture_merged { $ct->process_all() }; like( $output, qr/.*bar\.pl/ ); is( read_file("$root_dir/bin/bar.pl"), "#!/usr/bin/perl\nuse strict;\n\$d = 5;\n" ); done_testing(); Code-TidyAll-0.18/t/PaxHeader/author-Util.t000644 777777 777777 00000000212 12217370452 020552 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705348 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/author-Util.t000644 €ˆž«€q{Ì00000000347 12217370452 017540 0ustar00jonswart000000 000000 #!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Code::TidyAll::t::Util; Code::TidyAll::t::Util->runtests; Code-TidyAll-0.18/t/PaxHeader/Basic.t000644 777777 777777 00000000212 12217370452 017356 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705329 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/Basic.t000644 €ˆž«€q{Ì00000000120 12217370452 016331 0ustar00jonswart000000 000000 #!/usr/bin/perl use Code::TidyAll::t::Basic; Code::TidyAll::t::Basic->runtests; Code-TidyAll-0.18/t/PaxHeader/Conf.t000644 777777 777777 00000000212 12217370452 017222 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705330 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/Conf.t000644 €ˆž«€q{Ì00000000116 12217370452 016202 0ustar00jonswart000000 000000 #!/usr/bin/perl use Code::TidyAll::t::Conf; Code::TidyAll::t::Conf->runtests; Code-TidyAll-0.18/t/PaxHeader/Zglob.t000644 777777 777777 00000000212 12217370452 017412 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705331 18 SCHILY.nlink=1 Code-TidyAll-0.18/t/Zglob.t000644 €ˆž«€q{Ì00000000120 12217370452 016365 0ustar00jonswart000000 000000 #!/usr/bin/perl use Code::TidyAll::t::Zglob; Code::TidyAll::t::Zglob->runtests; Code-TidyAll-0.18/lib/PaxHeader/Code000775 777777 777777 00000000212 12217370452 017255 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705260 18 SCHILY.nlink=4 Code-TidyAll-0.18/lib/Code/000775 €ˆž«€q{Ì00000000000 12217370452 016311 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/PaxHeader/Pod000775 777777 777777 00000000212 12217370452 017125 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705321 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Pod/000775 €ˆž«€q{Ì00000000000 12217370452 016161 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/PaxHeader/Test000775 777777 777777 00000000212 12217370452 017322 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705325 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Test/000775 €ˆž«€q{Ì00000000000 12217370452 016356 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Test/PaxHeader/Code000775 777777 777777 00000000212 12217370452 020174 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705326 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Test/Code/000775 €ˆž«€q{Ì00000000000 12217370452 017230 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Test/Code/PaxHeader/TidyAll.pm000644 777777 777777 00000000212 12217370452 022144 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705327 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Test/Code/TidyAll.pm000644 €ˆž«€q{Ì00000004463 12217370452 021135 0ustar00jonswart000000 000000 package Test::Code::TidyAll; { $Test::Code::TidyAll::VERSION = '0.18'; } use IPC::System::Simple qw(run); use Code::TidyAll; use Test::Builder; use strict; use warnings; use base qw(Exporter); my $test = Test::Builder->new; our @EXPORT_OK = qw(tidyall_ok); our @EXPORT = @EXPORT_OK; sub tidyall_ok { my @conf_names = Code::TidyAll->default_conf_names; my $conf_file = Code::TidyAll->find_conf_file( \@conf_names, "." ); my $ct = Code::TidyAll->new_from_conf_file( $conf_file, check_only => 1, mode => 'test' ); my @files = $ct->find_matched_files; $test->plan( tests => scalar(@files) ); foreach my $file (@files) { my $desc = $ct->_small_path($file); my $result = $ct->process_file($file); if ( $result->ok ) { $test->ok( 1, $desc ); } else { $test->diag( $result->error ); $test->ok( 0, $desc ); } } } 1; __END__ =pod =head1 NAME Test::Code::TidyAll - check that all your files are tidy and valid according to tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In a file like 't/tidyall.t': #!/usr/bin/perl use Test::Code::TidyAll; tidyall_ok(); =head1 DESCRIPTION Uses L to check that all the files in your project are in a tidied and valid state, i.e. that no plugins throw errors or would change the contents of the file. Does not actually modify any files. By default, looks for config file C or C<.tidyallrc> in the current directory and parent directories, which is generally the right place if you are running L. Passes mode = "test" by default; see L. C is exported by default. Any options will be passed along to the L constructor. For example, if you don't want to use the tidyall cache and instead check all files every time: run_tests(no_cache => 1); or if you need to specify the config file: run_tests(conf_file => '/path/to/conf/file'); =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Pod/PaxHeader/Weaver000775 777777 777777 00000000212 12217370452 020356 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705322 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Pod/Weaver/000775 €ˆž«€q{Ì00000000000 12217370452 017412 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Pod/Weaver/PaxHeader/Section000775 777777 777777 00000000212 12217370452 021762 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705323 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Pod/Weaver/Section/000775 €ˆž«€q{Ì00000000000 12217370452 021016 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Pod/Weaver/Section/PaxHeader/SeeAlsoCodeTidyAll.pm000644 777777 777777 00000000212 12217370452 026001 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705324 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Pod/Weaver/Section/SeeAlsoCodeTidyAll.pm000644 €ˆž«€q{Ì00000002000 12217370452 024753 0ustar00jonswart000000 000000 package Pod::Weaver::Section::SeeAlsoCodeTidyAll; { $Pod::Weaver::Section::SeeAlsoCodeTidyAll::VERSION = '0.18'; } use Moose; with 'Pod::Weaver::Role::Section'; use Moose::Autobox; # Add "SEE ALSO: CodeTidyAll" sub weave_section { my ( $self, $document, $input ) = @_; my $idc = $input->{pod_document}->children; for ( my $i = 0 ; $i < $idc->length ; $i++ ) { next unless my $para = $idc->[$i]; return if $para->can('command') && $para->command eq 'head1' && $para->content eq 'SEE ALSO'; } $document->children->push( Pod::Elemental::Element::Nested->new( { command => 'head1', content => 'SEE ALSO', children => [ Pod::Elemental::Element::Pod5::Ordinary->new( { content => "L" } ), ], } ), ); } __PACKAGE__->meta->make_immutable; no Moose; 1; Code-TidyAll-0.18/lib/Code/PaxHeader/TidyAll000775 777777 777777 00000000213 12217370452 020620 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705262 19 SCHILY.nlink=13 Code-TidyAll-0.18/lib/Code/TidyAll/000775 €ˆž«€q{Ì00000000000 12217370452 017653 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/PaxHeader/TidyAll.pm000644 777777 777777 00000000212 12217370452 021225 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705261 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll.pm000644 €ˆž«€q{Ì00000042667 12217370452 020226 0ustar00jonswart000000 000000 package Code::TidyAll; { $Code::TidyAll::VERSION = '0.18'; } use Cwd qw(realpath); use Code::TidyAll::Config::INI::Reader; use Code::TidyAll::Cache; use Code::TidyAll::Util qw(abs2rel basename can_load dirname dump_one_line mkpath read_dir read_file rel2abs tempdir_simple uniq write_file); use Code::TidyAll::Result; use Date::Format; use Digest::SHA1 qw(sha1_hex); use File::Find qw(find); use File::Zglob; use List::MoreUtils qw(uniq); use Moo; use Time::Duration::Parse qw(parse_duration); use Try::Tiny; use strict; use warnings; sub default_conf_names { ( 'tidyall.ini', '.tidyallrc' ) } # External has 'backup_ttl' => ( is => 'ro', default => sub { '1 hour' } ); has 'check_only' => ( is => 'ro' ); has 'data_dir' => ( is => 'lazy' ); has 'iterations' => ( is => 'ro', default => sub { 1 } ); has 'list_only' => ( is => 'ro' ); has 'mode' => ( is => 'ro', default => sub { 'cli' } ); has 'no_backups' => ( is => 'ro' ); has 'no_cache' => ( is => 'ro' ); has 'output_suffix' => ( is => 'ro', default => sub { '' } ); has 'plugins' => ( is => 'ro', required => 1 ); has 'quiet' => ( is => 'ro' ); has 'recursive' => ( is => 'ro' ); has 'refresh_cache' => ( is => 'ro' ); has 'root_dir' => ( is => 'ro', required => 1 ); has 'verbose' => ( is => 'ro' ); # Internal has 'backup_dir' => ( is => 'lazy', init_arg => undef, trigger => 1 ); has 'backup_ttl_secs' => ( is => 'lazy', init_arg => undef ); has 'base_sig' => ( is => 'lazy', init_arg => undef ); has 'cache' => ( is => 'lazy', init_arg => undef ); has 'plugin_objects' => ( is => 'lazy', init_arg => undef ); has 'plugins_for_mode' => ( is => 'lazy', init_arg => undef ); sub _build_backup_dir { my $self = shift; return $self->data_dir . "/backups"; } sub _build_backup_ttl_secs { my $self = shift; return parse_duration( $self->backup_ttl ); } sub _build_base_sig { my $self = shift; my $active_plugins = join( "|", map { $_->name } @{ $self->plugin_objects } ); return $self->_sig( [ $Code::TidyAll::VERSION || 0, $active_plugins ] ); } sub _build_cache { my $self = shift; return Code::TidyAll::Cache->new( cache_dir => $self->data_dir . "/cache" ); } sub _build_data_dir { my $self = shift; return $self->root_dir . "/.tidyall.d"; } sub _build_plugins_for_mode { my $self = shift; my $plugins = $self->plugins; if ( my $mode = $self->mode ) { $plugins = { map { ( $_, $plugins->{$_} ) } grep { $self->_plugin_conf_matches_mode( $plugins->{$_}, $mode ) } keys(%$plugins) }; } return $plugins; } sub _build_plugin_objects { my $self = shift; my @plugin_objects = map { $self->_load_plugin( $_, $self->plugins->{$_} ) } keys( %{ $self->plugins_for_mode } ); # Sort tidiers before validators, then alphabetical # return [ sort { ( $a->is_validator <=> $b->is_validator ) || ( $a->name cmp $b->name ) } @plugin_objects ]; } sub BUILD { my ( $self, $params ) = @_; # Strict constructor # if ( my @bad_params = grep { !$self->can($_) } keys(%$params) ) { die sprintf( "unknown constructor param%s %s for %s", @bad_params > 1 ? "s" : "", join( ", ", sort map { "'$_'" } @bad_params ), ref($self) ); } $self->{root_dir} = realpath( $self->{root_dir} ); $self->{plugins_for_path} = {}; unless ( $self->no_backups ) { mkpath( $self->backup_dir, 0, 0775 ); $self->_purge_backups_periodically(); } } sub new_from_conf_file { my ( $class, $conf_file, %params ) = @_; die "no such file '$conf_file'" unless -f $conf_file; my $conf_params = $class->_read_conf_file($conf_file); my $main_params = delete( $conf_params->{'_'} ) || {}; %params = ( plugins => $conf_params, root_dir => realpath( dirname($conf_file) ), %$main_params, %params ); # Initialize with alternate class if given # if ( my $tidyall_class = delete( $params{tidyall_class} ) ) { die "cannot load '$tidyall_class'" unless can_load($tidyall_class); $class = $tidyall_class; } $class->msg( "constructing %s with these params: %s", $class, dump_one_line( \%params ) ) if ( $params{verbose} ); return $class->new(%params); } sub _load_plugin { my ( $self, $plugin_name, $plugin_conf ) = @_; # Extract first name in case there is a description # my ($plugin_fname) = ( $plugin_name =~ /^(\S+)/ ); my $plugin_class = ( $plugin_fname =~ /^\+/ ? substr( $plugin_fname, 1 ) : "Code::TidyAll::Plugin::$plugin_fname" ); try { can_load($plugin_class) || die "not found"; } catch { die "could not load plugin class '$plugin_class': $_"; }; return $plugin_class->new( class => $plugin_class, name => $plugin_name, tidyall => $self, %$plugin_conf ); } sub _plugin_conf_matches_mode { my ( $self, $conf, $mode ) = @_; if ( my $only_modes = $conf->{only_modes} ) { return 0 if ( " " . $only_modes . " " ) !~ / $mode /; } if ( my $except_modes = $conf->{except_modes} ) { return 0 if ( " " . $except_modes . " " ) =~ / $mode /; } return 1; } sub process_all { my $self = shift; return $self->process_paths( $self->find_matched_files ); } sub process_paths { my ( $self, @paths ) = @_; return map { $self->process_path( realpath($_) || rel2abs($_) ) } @paths; } sub process_path { my ( $self, $path ) = @_; if ( -d $path ) { if ( $self->recursive ) { return $self->process_paths( map { "$path/$_" } read_dir($path) ); } else { return ( $self->_error_result( "$path: is a directory (try -r/--recursive)", $path ) ); } } elsif ( -f $path ) { return ( $self->process_file($path) ); } else { return ( $self->_error_result( "$path: not a file or directory", $path ) ); } } sub process_file { my ( $self, $file ) = @_; die "$file is not a file" unless -f $file; my $path = $self->_small_path($file); if ( $self->list_only ) { if ( my @plugins = $self->plugins_for_path($path) ) { printf( "%s (%s)\n", $path, join( ", ", map { $_->name } @plugins ) ); } return Code::TidyAll::Result->new( path => $path, state => 'checked' ); } my $cache = $self->no_cache ? undef : $self->cache; my $cache_key = "sig/$path"; my $contents = my $orig_contents = read_file($file); if ( $cache && ( my $sig = $cache->get($cache_key) ) ) { if ( $self->refresh_cache ) { $cache->remove($cache_key); } elsif ( $sig eq $self->_file_sig( $file, $orig_contents ) ) { $self->msg( "[cached] %s", $path ) if $self->verbose; return Code::TidyAll::Result->new( path => $path, state => 'cached' ); } } my $result = $self->process_source( $orig_contents, $path ); if ( $result->state eq 'tidied' ) { $self->_backup_file( $path, $contents ); $contents = $result->new_contents; write_file( join( '', $file, $self->output_suffix ), $contents ); } $cache->set( $cache_key, $self->_file_sig( $file, $contents ) ) if $cache && $result->ok; return $result; } sub process_source { my ( $self, $contents, $path ) = @_; die "contents and path required" unless defined($contents) && defined($path); my @plugins = $self->plugins_for_path($path); if ( !@plugins ) { $self->msg( "[no plugins apply%s] %s", $self->mode ? " for mode '" . $self->mode . "'" : "", $path ) if $self->verbose; return Code::TidyAll::Result->new( path => $path, state => 'no_match' ); } my $basename = basename($path); my $error; my $new_contents = my $orig_contents = $contents; my $plugin; try { foreach my $method (qw(preprocess_source process_source_or_file postprocess_source)) { foreach $plugin (@plugins) { $new_contents = $plugin->$method( $new_contents, $basename ); } } } catch { chomp; $error = $_; $error = sprintf( "*** '%s': %s", $plugin->name, $_ ) if $plugin; }; my $was_tidied = !$error && ( $new_contents ne $orig_contents ); if ( $was_tidied && $self->check_only ) { $error = "*** needs tidying"; undef $was_tidied; } if ( !$self->quiet || $error ) { my $status = $was_tidied ? "[tidied] " : "[checked] "; my $plugin_names = $self->verbose ? sprintf( " (%s)", join( ", ", map { $_->name } @plugins ) ) : ""; $self->msg( "%s%s%s", $status, $path, $plugin_names ); } if ($error) { return $self->_error_result( $error, $path ); } elsif ($was_tidied) { return Code::TidyAll::Result->new( path => $path, state => 'tidied', new_contents => $new_contents ); } else { return Code::TidyAll::Result->new( path => $path, state => 'checked' ); } } sub _read_conf_file { my ( $class, $conf_file ) = @_; my $conf_string = read_file($conf_file); my $root_dir = dirname($conf_file); $conf_string =~ s/\$ROOT/$root_dir/g; my $conf_hash = Code::TidyAll::Config::INI::Reader->read_string($conf_string); die "'$conf_file' did not evaluate to a hash" unless ( ref($conf_hash) eq 'HASH' ); return $conf_hash; } sub _backup_file { my ( $self, $path, $contents ) = @_; unless ( $self->no_backups ) { my $backup_file = join( "/", $self->backup_dir, $self->_backup_filename($path) ); mkpath( dirname($backup_file), 0, 0775 ); write_file( $backup_file, $contents ); } } sub _backup_filename { my ( $self, $path ) = @_; return join( "", $path, "-", time2str( "%Y%m%d-%H%M%S", time ), ".bak" ); } sub _purge_backups_periodically { my ($self) = @_; my $cache = $self->cache; my $last_purge_backups = $cache->get("last_purge_backups") || 0; if ( time > $last_purge_backups + $self->backup_ttl_secs ) { $self->_purge_backups(); $cache->set( "last_purge_backups", time() ); } } sub _purge_backups { my ($self) = @_; $self->msg("purging old backups") if $self->verbose; find( { follow => 0, wanted => sub { unlink $_ if -f && /\.bak$/ && time > ( stat($_) )[9] + $self->backup_ttl_secs; }, no_chdir => 1 }, $self->backup_dir ); } sub find_conf_file { my ( $class, $conf_names, $start_dir ) = @_; my $path1 = rel2abs($start_dir); my $path2 = realpath($start_dir); my $conf_file = $class->_find_conf_file_upward( $conf_names, $path1 ) || $class->_find_conf_file_upward( $conf_names, $path2 ); unless ( defined $conf_file ) { die sprintf( "could not find %s upwards from %s", join( " or ", @$conf_names ), ( $path1 eq $path2 ) ? "'$path1'" : "'$path1' or '$path2'" ); } return $conf_file; } sub _find_conf_file_upward { my ( $class, $conf_names, $search_dir ) = @_; $search_dir =~ s{/+$}{}; my $cnt = 0; while (1) { foreach my $conf_name (@$conf_names) { my $try_path = "$search_dir/$conf_name"; return $try_path if ( -f $try_path ); } if ( $search_dir eq '/' ) { return undef; } else { $search_dir = dirname($search_dir); } die "inf loop!" if ++$cnt > 100; } } sub find_matched_files { my ($self) = @_; my @matched_files; my $plugins_for_path = $self->{plugins_for_path}; my $root_length = length( $self->root_dir ); foreach my $plugin ( @{ $self->plugin_objects } ) { my @selected = grep { -f && !-l } $self->_zglob( $plugin->selects ); if ( @{ $plugin->ignores } ) { my %is_ignored = map { ( $_, 1 ) } $self->_zglob( $plugin->ignores ); @selected = grep { !$is_ignored{$_} } @selected; } push( @matched_files, @selected ); foreach my $file (@selected) { my $path = substr( $file, $root_length + 1 ); $plugins_for_path->{$path} ||= []; push( @{ $plugins_for_path->{$path} }, $plugin ); } } return sort( uniq(@matched_files) ); } sub plugins_for_path { my ( $self, $path ) = @_; $self->{plugins_for_path}->{$path} ||= [ grep { $_->matches_path($path) } @{ $self->plugin_objects } ]; return @{ $self->{plugins_for_path}->{$path} }; } sub _zglob { my ( $self, $globs ) = @_; local $File::Zglob::NOCASE = 0; my @files; foreach my $glob (@$globs) { try { push( @files, File::Zglob::zglob( join( "/", $self->root_dir, $glob ) ) ); } catch { die "error parsing '$glob': $_"; } } return uniq(@files); } sub _small_path { my ( $self, $path ) = @_; die sprintf( "'%s' is not underneath root dir '%s'!", $path, $self->root_dir ) unless index( $path, $self->root_dir ) == 0; return substr( $path, length( $self->root_dir ) + 1 ); } sub _file_sig { my ( $self, $file, $contents ) = @_; my $last_mod = ( stat($file) )[9]; return $self->_sig( [ $self->base_sig, $last_mod, $contents ] ); } sub _sig { my ( $self, $data ) = @_; return sha1_hex( join( ",", @$data ) ); } sub _tempdir { my ($self) = @_; $self->{tempdir} ||= tempdir_simple(); return $self->{tempdir}; } sub msg { my ( $self, $format, @params ) = @_; printf "$format\n", @params; } sub _error_result { my ( $self, $msg, $path ) = @_; $self->msg( "%s", $msg ); return Code::TidyAll::Result->new( path => $path, state => 'error', error => $msg ); } 1; __END__ =pod =head1 NAME Code::TidyAll - Engine for tidyall, your all-in-one code tidier and validator =head1 VERSION version 0.18 =head1 SYNOPSIS use Code::TidyAll; my $ct = Code::TidyAll->new_from_conf_file( '/path/to/conf/file', ... ); # or my $ct = Code::TidyAll->new( root_dir => '/path/to/root', plugins => { perltidy => { select => 'lib/**/*.(pl|pm)', argv => '-noll -it=2', }, ... } ); # then... $ct->process_paths($file1, $file2); =head1 DESCRIPTION This is the engine used by L - read that first to get an overview. You can call this API from your own program instead of executing C. =head1 CONSTRUCTION =head2 Constructor methods =over =item new (%params) The regular constructor. Must pass at least I and I. =item new_with_conf_file ($conf_file, %params) Takes a conf file path, followed optionally by a set of key/value parameters. Reads parameters out of the conf file and combines them with the passed parameters (the latter take precedence), and calls the regular constructor. If the conf file or params defines I, then that class is constructed instead of C. =back =head2 Constructor parameters =over =item plugins Specify a hash of plugins, each of which is itself a hash of options. This is equivalent to what would be parsed out of the sections in the configuration file. =item backup_ttl =item check_only =item data_dir =item iterations =item mode =item no_backups =item no_cache =item output_suffix =item quiet =item root_dir =item verbose These options are the same as the equivalent C command-line options, replacing dashes with underscore (e.g. the C option becomes C here). =back =head1 METHODS =over =item process_paths (path, ...) Call L on each file; descend recursively into each directory if the C flag is on. Return a list of L objects, one for each file. =item process_file (file) Process the I, meaning =over =item * Check the cache and return immediately if file has not changed =item * Apply appropriate matching plugins =item * Print success or failure result to STDOUT, depending on quiet/verbose settings =item * Write the cache if enabled =item * Return a L object =back =item process_source (I, I) Like L, but process the I string instead of a file, and do not read from or write to the cache. You must still pass the relative I from the root as the second argument, so that we know which plugins to apply. Return a L object. =item plugins_for_path (I) Given a relative I from the root, return a list of L objects that apply to it, or an empty list if no plugins apply. =item find_conf_file (I, I) Class method. Start in the I and work upwards, looking for one of the I. Return the pathname if found or throw an error if not found. =item find_matched_files Returns a list of sorted files that match at least one plugin in configuration. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Cache.pm000644 777777 777777 00000000212 12217370452 022230 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705263 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Cache.pm000644 €ˆž«€q{Ì00000001550 12217370452 021213 0ustar00jonswart000000 000000 package Code::TidyAll::Cache; { $Code::TidyAll::Cache::VERSION = '0.18'; } use Digest::SHA1 qw(sha1_hex); use Code::TidyAll::Util qw(dirname mkpath read_file write_file); use Moo; has 'cache_dir' => ( is => 'ro', required => 1 ); sub path_to_key { my ( $self, $key ) = @_; my $sig = sha1_hex($key); return join( "/", $self->cache_dir, substr( $sig, 0, 1 ), "$sig.dat" ); } sub get { my ( $self, $key ) = @_; my $file = $self->path_to_key($key); if ( defined $file && -f $file ) { return read_file($file); } else { return undef; } } sub set { my ( $self, $key, $value ) = @_; my $file = $self->path_to_key($key); mkpath( dirname($file), 0, 0775 ); write_file( $file, $value ); } sub remove { my ( $self, $key, $value ) = @_; my $file = $self->path_to_key($key); unlink($file); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Config000775 777777 777777 00000000212 12217370452 022024 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705267 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Code/TidyAll/Config/000775 €ˆž«€q{Ì00000000000 12217370452 021060 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Git000775 777777 777777 00000000212 12217370452 021342 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705270 18 SCHILY.nlink=5 Code-TidyAll-0.18/lib/Code/TidyAll/Git/000775 €ˆž«€q{Ì00000000000 12217370452 020376 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Plugin000775 777777 777777 00000000213 12217370452 022056 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705274 19 SCHILY.nlink=14 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/000775 €ˆž«€q{Ì00000000000 12217370452 021111 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Plugin.pm000644 777777 777777 00000000212 12217370452 022463 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705264 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin.pm000644 €ˆž«€q{Ì00000017062 12217370452 021453 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin; { $Code::TidyAll::Plugin::VERSION = '0.18'; } use Code::TidyAll::Util qw(basename read_file write_file); use Code::TidyAll::Util::Zglob qw(zglobs_to_regex); use Scalar::Util qw(weaken); use Moo; # External has 'argv' => ( is => 'ro', default => sub { '' } ); has 'class' => ( is => 'ro' ); has 'cmd' => ( is => 'lazy' ); has 'ignore' => ( is => 'ro' ); has 'is_tidier' => ( is => 'lazy' ); has 'is_validator' => ( is => 'lazy' ); has 'name' => ( is => 'ro', required => 1 ); has 'select' => ( is => 'ro' ); has 'tidyall' => ( is => 'ro', required => 1, weak_ref => 1 ); # Internal has 'ignore_regex' => ( is => 'lazy' ); has 'ignores' => ( is => 'lazy' ); has 'select_regex' => ( is => 'lazy' ); has 'selects' => ( is => 'lazy' ); sub _build_cmd { die "no default cmd specified"; } sub _build_selects { my ($self) = @_; die sprintf( "select is required for '%s'", $self->name ) unless defined( $self->select ); return $self->_parse_zglob_list( $self->select ); } sub _build_select_regex { my ($self) = @_; return zglobs_to_regex( @{ $self->selects } ); } sub _build_ignores { my ($self) = @_; return $self->_parse_zglob_list( $self->ignore ); } sub _build_ignore_regex { my ($self) = @_; return zglobs_to_regex( @{ $self->ignores } ); } sub _build_is_tidier { my ($self) = @_; return ( $self->can('transform_source') || $self->can('transform_file') ) ? 1 : 0; } sub _build_is_validator { my ($self) = @_; return ( $self->can('validate_source') || $self->can('validate_file') ) ? 1 : 0; } sub BUILD { my ( $self, $params ) = @_; # Strict constructor # $self->validate_params($params); } sub validate_params { my ( $self, $params ) = @_; delete( $params->{only_modes} ); delete( $params->{except_modes} ); if ( my @bad_params = grep { !$self->can($_) } keys(%$params) ) { die sprintf( "unknown option%s %s for plugin '%s'", @bad_params > 1 ? "s" : "", join( ", ", sort map { "'$_'" } @bad_params ), $self->name ); } } sub _parse_zglob_list { my ( $self, $zglob_list ) = @_; $zglob_list = '' if !defined($zglob_list); my @zglobs = split( /\s+/, $zglob_list ); if ( my ($bad_zglob) = ( grep { m{^/} } @zglobs ) ) { die "zglob '$bad_zglob' should not begin with slash"; } return \@zglobs; } # No-ops by default; may be overridden in subclass sub preprocess_source { return $_[1]; } sub postprocess_source { return $_[1]; } sub process_source_or_file { my ( $self, $source, $basename ) = @_; if ( $self->can('transform_source') ) { foreach my $iter ( 1 .. $self->tidyall->iterations ) { $source = $self->transform_source($source); } } if ( $self->can('transform_file') ) { my $tempfile = $self->_write_temp_file( $basename, $source ); foreach my $iter ( 1 .. $self->tidyall->iterations ) { $self->transform_file($tempfile); } $source = read_file($tempfile); } if ( $self->can('validate_source') ) { $self->validate_source($source); } if ( $self->can('validate_file') ) { my $tempfile = $self->_write_temp_file( $basename, $source ); $self->validate_file($tempfile); } return $source; } sub _write_temp_file { my ( $self, $basename, $source ) = @_; my $tempfile = join( "/", $self->tidyall->_tempdir(), $basename ); write_file( $tempfile, $source ); return $tempfile; } sub matches_path { my ( $self, $path ) = @_; return $path =~ $self->select_regex && $path !~ $self->ignore_regex; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin - Create plugins for tidying or validating code =head1 VERSION version 0.18 =head1 SYNOPSIS package Code::TidyAll::Plugin::SomeTidier; use Moo; extends 'Code::TidyAll::Plugin'; sub transform_source { my ( $self, source ) = @_; ... return $source; } package Code::TidyAll::Plugin::SomeValidator; use Moo; extends 'Code::TidyAll::Plugin'; sub validate_file { my ( $self, $file ) = @_; die "not valid" if ...; } =head1 DESCRIPTION To use a tidier or validator with C it must have a corresponding plugin class that inherits from this class. This document describes how to implement a new plugin. The easiest way to start is to look at existing plugins, such as L and L. =head1 NAMING If you are going to publicly release your plugin, call it 'Code::TidyAll::Plugin::I' so that users can find it easily and refer to it by its short name in configuration. If it's an internal plugin, you can call it whatever you like and refer to it with a plus sign prefix in the config file, e.g. [+My::Tidier::Class] select = **/*.{pl,pm,t} =head1 CONSTRUCTOR AND ATTRIBUTES Your plugin constructor will be called with the configuration key/value pairs as parameters. e.g. given [PerlCritic] select = lib/**/*.pm ignore = lib/UtterHack.pm argv = -severity 3 then L would be constructed with parameters select => 'lib/**/*.pm', ignore = 'lib/UtterHack.pm', argv = '-severity 3' The following attributes are part of this base class. Your subclass can declare others, of course. =over =item argv A standard attribute for passing command line arguments. =item cmd A standard attribute for specifying the name of the command to run, e.g. "/usr/local/bin/perlcritic". =item name Name of the plugin to be used in error messages etc. =item tidyall A weak reference back to the L object. =item select, ignore Select and ignore patterns - you can ignore these. =back =head1 METHODS Your plugin may define one or more of these methods. They are all no-ops by default. =over =item preprocess_source ($source) Receives source code as a string; returns the processed string, or dies with error. This runs on all plugins I any of the other methods. =item transform_source ($source) Receives source code as a string; returns the transformed string, or dies with error. This is repeated multiple times if --iterations was passed or specified in the configuration file. =item transform_file ($file) Receives filename; transforms the file in place, or dies with error. Note that the file will be a temporary copy of the user's file with the same basename; your changes will only propagate back if there was no error reported from any plugin. This is repeated multiple times if --iterations was passed or specified in the configuration file. =item validate_source ($source) Receives source code as a string; dies with error if invalid. Return value will be ignored. =item validate_file ($file) Receives filename; validates file and dies with error if invalid. Should not modify file! Return value will be ignored. =item postprocess_source ($source) Receives source code as a string; returns the processed string, or dies with error. This runs on all plugins I any of the other methods. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Result.pm000644 777777 777777 00000000212 12217370452 022503 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705265 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Result.pm000644 €ˆž«€q{Ì00000003422 12217370452 021466 0ustar00jonswart000000 000000 package Code::TidyAll::Result; { $Code::TidyAll::Result::VERSION = '0.18'; } use Moo; has 'error' => ( is => 'ro' ); has 'new_contents' => ( is => 'ro' ); has 'path' => ( is => 'ro' ); has 'state' => ( is => 'ro' ); sub ok { return $_[0]->state ne 'error' } 1; __END__ =pod =head1 NAME Code::TidyAll::Result - Result returned from processing a file/source =head1 VERSION version 0.18 =head1 SYNOPSIS my $ct = Code::TidyAll->new(...); my $result = $ct->process_file($file); if ($result->error) { ... } =head1 DESCRIPTION Represents the result of L and L. A list of these is returned from L. =head1 METHODS =over =item path The path that was processed, relative to the root (e.g. "lib/Foo.pm") =item state A string, one of =over =item C - No plugins matched this file =item C - Cache hit (file had not changed since last processed) =item C - An error occurred while applying one of the plugins =item C - File was successfully checked and did not change =item C - File was successfully checked and changed =back =item new_contents Contains the new contents if state is 'tidied' =item error Contains the error message if state is 'error' =item ok Returns true iff state is not 'error' =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/SVN000775 777777 777777 00000000212 12217370452 021265 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705287 18 SCHILY.nlink=4 Code-TidyAll-0.18/lib/Code/TidyAll/SVN/000775 €ˆž«€q{Ì00000000000 12217370452 020321 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/t000775 777777 777777 00000000213 12217370452 021063 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705290 19 SCHILY.nlink=10 Code-TidyAll-0.18/lib/Code/TidyAll/t/000775 €ˆž«€q{Ì00000000000 12217370452 020116 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Test000775 777777 777777 00000000212 12217370452 021536 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705311 18 SCHILY.nlink=4 Code-TidyAll-0.18/lib/Code/TidyAll/Test/000775 €ˆž«€q{Ì00000000000 12217370452 020572 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Util000775 777777 777777 00000000212 12217370452 021534 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705319 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Code/TidyAll/Util/000775 €ˆž«€q{Ì00000000000 12217370452 020570 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/PaxHeader/Util.pm000644 777777 777777 00000000212 12217370452 022142 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705266 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Util.pm000644 €ˆž«€q{Ì00000003730 12217370452 021127 0ustar00jonswart000000 000000 package Code::TidyAll::Util; { $Code::TidyAll::Util::VERSION = '0.18'; } use Cwd qw(realpath); use Data::Dumper; use File::Basename; use File::Path; use File::Spec::Functions qw(abs2rel rel2abs); use File::Temp qw(tempdir); use Guard; use List::MoreUtils qw(uniq); use Try::Tiny; use strict; use warnings; use base qw(Exporter); our @EXPORT_OK = qw(abs2rel basename can_load dirname dump_one_line mkpath pushd read_dir read_file realpath rel2abs tempdir_simple trim uniq write_file); sub can_load { # Load $class_name if possible. Return 1 if successful, 0 if it could not be # found, and rethrow load error (other than not found). # my ($class_name) = @_; my $result; try { eval "require $class_name"; ## no critic die $@ if $@; $result = 1; } catch { if ( /Can\'t locate .* in \@INC/ && !/Compilation failed/ ) { $result = 0; } else { die $_; } }; return $result; } sub tempdir_simple { my $template = shift || 'Code-TidyAll-XXXX'; return realpath( tempdir( $template, TMPDIR => 1, CLEANUP => 1 ) ); } sub dump_one_line { my ($value) = @_; return Data::Dumper->new( [$value] )->Indent(0)->Sortkeys(1)->Quotekeys(0)->Terse(1)->Dump(); } sub pushd { my ($dir) = @_; my $cwd = realpath(); chdir($dir); return guard { chdir($cwd) }; } sub trim { my ($str) = @_; for ($str) { s/^\s+//; s/\s+$// } return $str; } sub read_dir { my ($dir) = @_; opendir( my $dirh, $dir ) or die "could not open $dir: $!"; my @dir_entries = grep { $_ ne "." && $_ ne ".." } readdir($dirh); return @dir_entries; } sub read_file { my ($file) = @_; open( my $fh, "<", $file ) or die "could not open $file: $!"; my $contents = do { local $/; <$fh> }; return $contents; } sub write_file { my ( $file, $contents ) = @_; open( my $fh, ">", $file ) or die "could not open $file: $!"; print $fh $contents; } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Util/PaxHeader/Zglob.pm000644 777777 777777 00000000212 12217370452 023217 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705320 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Util/Zglob.pm000644 €ˆž«€q{Ì00000005436 12217370452 022211 0ustar00jonswart000000 000000 # This is a copy of Text::Glob, modified to support "**/" # package Code::TidyAll::Util::Zglob; { $Code::TidyAll::Util::Zglob::VERSION = '0.18'; } use strict; use Exporter; use vars qw/@ISA @EXPORT_OK $strict_leading_dot $strict_wildcard_slash/; @ISA = 'Exporter'; @EXPORT_OK = qw( zglobs_to_regex zglob_to_regex ); $strict_leading_dot = 1; $strict_wildcard_slash = 1; use constant debug => 0; sub zglobs_to_regex { my @globs = @_; return @globs ? join( '|', map { "(?:" . zglob_to_regex($_) . ")" } @globs ) : qr/(?!)/; } sub zglob_to_regex { my $glob = shift; my $regex = zglob_to_regex_string($glob); return qr/^$regex$/; } sub zglob_to_regex_string { my $glob = shift; my ( $regex, $in_curlies, $escaping ); local $_; my $first_byte = 1; $glob =~ s/\*\*\//\cZ/g; # convert **/ to single character for ( $glob =~ m/(.)/gs ) { if ($first_byte) { if ($strict_leading_dot) { $regex .= '(?=[^\.])' unless $_ eq '.'; } $first_byte = 0; } if ( $_ eq '/' ) { $first_byte = 1; } if ( $_ eq '.' || $_ eq '(' || $_ eq ')' || $_ eq '|' || $_ eq '+' || $_ eq '^' || $_ eq '$' || $_ eq '@' || $_ eq '%' ) { $regex .= "\\$_"; } elsif ( $_ eq "\cZ" ) { # handle **/ - if escaping, only escape first * $regex .= $escaping ? ( "\\*" . ( $strict_wildcard_slash ? "[^/]*" : ".*" ) . "/" ) : ".*"; } elsif ( $_ eq '*' ) { $regex .= $escaping ? "\\*" : $strict_wildcard_slash ? "[^/]*" : ".*"; } elsif ( $_ eq '?' ) { $regex .= $escaping ? "\\?" : $strict_wildcard_slash ? "[^/]" : "."; } elsif ( $_ eq '{' ) { $regex .= $escaping ? "\\{" : "("; ++$in_curlies unless $escaping; } elsif ( $_ eq '}' && $in_curlies ) { $regex .= $escaping ? "}" : ")"; --$in_curlies unless $escaping; } elsif ( $_ eq ',' && $in_curlies ) { $regex .= $escaping ? "," : "|"; } elsif ( $_ eq "\\" ) { if ($escaping) { $regex .= "\\\\"; $escaping = 0; } else { $escaping = 1; } next; } else { $regex .= $_; $escaping = 0; } $escaping = 0; } print "# $glob $regex\n" if debug; return $regex; } 1; __END__ Code-TidyAll-0.18/lib/Code/TidyAll/Test/PaxHeader/Class.pm000644 777777 777777 00000000212 12217370452 023211 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705312 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Class.pm000644 €ˆž«€q{Ì00000000277 12217370452 022201 0ustar00jonswart000000 000000 package Code::TidyAll::Test::Class; { $Code::TidyAll::Test::Class::VERSION = '0.18'; } use Test::Class::Most; use strict; use warnings; __PACKAGE__->SKIP_CLASS("abstract base class"); 1; Code-TidyAll-0.18/lib/Code/TidyAll/Test/PaxHeader/Plugin000775 777777 777777 00000000212 12217370452 022774 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705313 18 SCHILY.nlink=7 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/000775 €ˆž«€q{Ì00000000000 12217370452 022030 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/PaxHeader/AToZ.pm000644 777777 777777 00000000212 12217370452 024217 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705314 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/AToZ.pm000644 €ˆž«€q{Ì00000000550 12217370452 023201 0ustar00jonswart000000 000000 package Code::TidyAll::Test::Plugin::AToZ; { $Code::TidyAll::Test::Plugin::AToZ::VERSION = '0.18'; } use Moo; extends 'Code::TidyAll::Plugin'; sub preprocess_source { my ( $self, $source ) = @_; $source =~ tr/Aa/Zz/; return $source; } sub postprocess_source { my ( $self, $source ) = @_; $source =~ tr/Zz/Aa/; return $source; } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/PaxHeader/CheckUpper.pm000644 777777 777777 00000000212 12217370452 025433 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705315 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/CheckUpper.pm000644 €ˆž«€q{Ì00000000413 12217370452 024413 0ustar00jonswart000000 000000 package Code::TidyAll::Test::Plugin::CheckUpper; { $Code::TidyAll::Test::Plugin::CheckUpper::VERSION = '0.18'; } use Moo; extends 'Code::TidyAll::Plugin'; sub validate_source { my ( $self, $source ) = @_; die "lowercase found" if $source =~ /[a-z]/; } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/PaxHeader/RepeatFoo.pm000644 777777 777777 00000000212 12217370452 025266 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705316 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/RepeatFoo.pm000644 €ˆž«€q{Ì00000000602 12217370452 024246 0ustar00jonswart000000 000000 package Code::TidyAll::Test::Plugin::RepeatFoo; { $Code::TidyAll::Test::Plugin::RepeatFoo::VERSION = '0.18'; } use Code::TidyAll::Util qw(read_file write_file); use Moo; extends 'Code::TidyAll::Plugin'; has 'times' => ( is => 'ro' ); sub transform_source { my ( $self, $source ) = @_; my $times = $self->times || die "no times specified"; return $source x $times; } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/PaxHeader/ReverseFoo.pm000644 777777 777777 00000000212 12217370452 025461 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705317 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/ReverseFoo.pm000644 €ˆž«€q{Ì00000000511 12217370452 024440 0ustar00jonswart000000 000000 package Code::TidyAll::Test::Plugin::ReverseFoo; { $Code::TidyAll::Test::Plugin::ReverseFoo::VERSION = '0.18'; } use Code::TidyAll::Util qw(read_file write_file); use Moo; extends 'Code::TidyAll::Plugin'; sub transform_file { my ( $self, $file ) = @_; write_file( $file, scalar( reverse( read_file($file) ) ) ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/PaxHeader/UpperText.pm000644 777777 777777 00000000212 12217370452 025342 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705318 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Test/Plugin/UpperText.pm000644 €ˆž«€q{Ì00000000527 12217370452 024330 0ustar00jonswart000000 000000 package Code::TidyAll::Test::Plugin::UpperText; { $Code::TidyAll::Test::Plugin::UpperText::VERSION = '0.18'; } use Moo; extends 'Code::TidyAll::Plugin'; sub transform_source { my ( $self, $source ) = @_; if ( $source =~ /^[A-Z]*$/i ) { return uc($source); } else { die "non-alpha content found"; } } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Basic.pm000644 777777 777777 00000000212 12217370452 022511 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705291 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Basic.pm000644 €ˆž«€q{Ì00000036336 12217370452 021506 0ustar00jonswart000000 000000 package Code::TidyAll::t::Basic; { $Code::TidyAll::t::Basic::VERSION = '0.18'; } use Cwd qw(realpath); use Code::TidyAll::Util qw(dirname mkpath pushd read_file tempdir_simple write_file); use Code::TidyAll; use Capture::Tiny qw(capture capture_stdout capture_merged); use File::Find qw(find); use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; sub test_plugin { "+Code::TidyAll::Test::Plugin::$_[0]" } my %UpperText = ( test_plugin('UpperText') => { select => '**/*.txt' } ); my %ReverseFoo = ( test_plugin('ReverseFoo') => { select => '**/foo*' } ); my %RepeatFoo = ( test_plugin('RepeatFoo') => { select => '**/foo*' } ); my %CheckUpper = ( test_plugin('CheckUpper') => { select => '**/*.txt' } ); my %AToZ = ( test_plugin('AToZ') => { select => '**/*.txt' } ); my $cli_conf; sub create_dir { my ( $self, $files ) = @_; my $root_dir = tempdir_simple(); while ( my ( $path, $content ) = each(%$files) ) { my $full_path = "$root_dir/$path"; mkpath( dirname($full_path), 0, 0775 ); write_file( $full_path, $content ); } return realpath($root_dir); } sub tidy { my ( $self, %params ) = @_; my $desc = $params{desc}; if ( !defined($desc) ) { ($desc) = ( ( caller(1) )[3] =~ /([^:]+$)/ ); } my $root_dir = $self->create_dir( $params{source} ); my $options = $params{options} || {}; my $ct = Code::TidyAll->new( plugins => $params{plugins}, root_dir => $root_dir, %$options ); my @results; my $output = capture_stdout { @results = $ct->process_all() }; my $error_count = grep { $_->error } @results; if ( $params{errors} ) { like( $output, $params{errors}, "$desc - errors" ); ok( $error_count > 0, "$desc - error_count > 0" ); } else { is( $error_count, 0, "$desc - error_count == 0" ); } while ( my ( $path, $content ) = each( %{ $params{dest} } ) ) { is( read_file("$root_dir/$path"), $content, "$desc - $path content" ); } if ( my $like_output = $params{like_output} ) { like( $output, $like_output, "$desc - output" ); } } sub test_basic : Tests { my $self = shift; $self->tidy( plugins => {}, source => { "foo.txt" => "abc" }, dest => { "foo.txt" => "abc" }, desc => 'one file no plugins', ); $self->tidy( plugins => {%UpperText}, source => { "foo.txt" => "abc" }, dest => { "foo.txt" => "ABC" }, desc => 'one file UpperText', ); $self->tidy( plugins => { test_plugin('UpperText') => { select => '**/*.txt', only_modes => 'upper' }, test_plugin('ReverseFoo') => { select => '**/foo*', only_modes => 'reversals' } }, source => { "foo.txt" => "abc" }, dest => { "foo.txt" => "cba" }, desc => 'one file reversals mode', options => { mode => 'reversals' }, ); $self->tidy( plugins => { %UpperText, %ReverseFoo }, source => { "foo.txt" => "abc", "bar.txt" => "def", "foo.tx" => "ghi", "bar.tx" => "jkl" }, dest => { "foo.txt" => "CBA", "bar.txt" => "DEF", "foo.tx" => "ihg", "bar.tx" => "jkl" }, desc => 'four files UpperText ReverseFoo', ); $self->tidy( plugins => {%UpperText}, source => { "foo.txt" => "abc1" }, dest => { "foo.txt" => "abc1" }, desc => 'one file UpperText errors', errors => qr/non-alpha content/ ); } sub test_multiple_plugin_instances : Tests { my $self = shift; $self->tidy( plugins => { test_plugin('RepeatFoo for txt') => { select => '**/*.txt', times => 2 }, test_plugin('RepeatFoo for foo') => { select => '**/foo.*', times => 3 }, %UpperText }, source => { "foo.txt" => "abc", "foo.dat" => "def", "bar.txt" => "ghi" }, dest => { "foo.txt" => scalar( "ABC" x 6 ), "foo.dat" => scalar( "def" x 3 ), "bar.txt" => scalar( "GHI" x 2 ) } ); } sub test_plugin_order_and_atomicity : Tests { my $self = shift; my @plugins = map { ( %ReverseFoo, test_plugin("UpperText $_") => { select => '**/*.txt' }, test_plugin("CheckUpper $_") => { select => '**/*.txt' } ) } ( 1 .. 3 ); my $output = capture_stdout { $self->tidy( plugins => {@plugins}, options => { verbose => 1 }, source => { "foo.txt" => "abc" }, dest => { "foo.txt" => "CBA" }, like_output => qr/.*ReverseFoo, .*UpperText 1, .*UpperText 2, .*UpperText 3, .*CheckUpper 1, .*CheckUpper 2, .*CheckUpper 3/ ); }; $self->tidy( plugins => { %AToZ, %ReverseFoo, %CheckUpper }, options => { verbose => 1 }, source => { "foo.txt" => "abc" }, dest => { "foo.txt" => "abc" }, errors => qr/lowercase found/, like_output => qr/foo.txt (.*ReverseFoo, .*CheckUpper)/ ); } sub test_quiet_and_verbose : Tests { my $self = shift; foreach my $state ( 'normal', 'quiet', 'verbose' ) { foreach my $error ( 0, 1 ) { my $root_dir = $self->create_dir( { "foo.txt" => ( $error ? "123" : "abc" ) } ); my $output = capture_stdout { my $ct = Code::TidyAll->new( plugins => {%UpperText}, root_dir => $root_dir, ( $state eq 'normal' ? () : ( $state => 1 ) ) ); $ct->process_paths("$root_dir/foo.txt"); }; if ($error) { like( $output, qr/non-alpha content found/, "non-alpha content found ($state)" ); } else { is( $output, "[tidied] foo.txt\n" ) if $state eq 'normal'; is( $output, "" ) if $state eq 'quiet'; like( $output, qr/purging old backups/, "purging old backups ($state)" ) if $state eq 'verbose'; like( $output, qr/\[tidied\] foo\.txt \(\+Code::TidyAll::Test::Plugin::UpperText\)/s, "foo.txt ($state)" ) if $state eq 'verbose'; } } } } sub test_iterations : Tests { my $self = shift; my $root_dir = $self->create_dir( { "foo.txt" => "abc" } ); my $ct = Code::TidyAll->new( plugins => { test_plugin('RepeatFoo') => { select => '**/foo*', times => 3 } }, root_dir => $root_dir, iterations => 2 ); my $file = "$root_dir/foo.txt"; $ct->process_paths($file); is( read_file($file), scalar( "abc" x 9 ), "3^2 = 9" ); } sub test_caching_and_backups : Tests { my $self = shift; foreach my $no_cache ( 0 .. 1 ) { foreach my $no_backups ( 0 .. 1 ) { my $desc = "(no_cache=$no_cache, no_backups=$no_backups)"; my $root_dir = $self->create_dir( { "foo.txt" => "abc" } ); my $ct = Code::TidyAll->new( plugins => {%UpperText}, root_dir => $root_dir, ( $no_cache ? ( no_cache => 1 ) : () ), ( $no_backups ? ( no_backups => 1 ) : () ) ); my $output; my $file = "$root_dir/foo.txt"; my $go = sub { $output = capture_stdout { $ct->process_paths($file) }; }; $go->(); is( read_file($file), "ABC", "first file change $desc" ); is( $output, "[tidied] foo.txt\n", "first output $desc" ); $go->(); if ($no_cache) { is( $output, "[checked] foo.txt\n", "second output $desc" ); } else { is( $output, '', "second output $desc" ); } write_file( $file, "ABCD" ); $go->(); is( $output, "[checked] foo.txt\n", "third output $desc" ); write_file( $file, "def" ); $go->(); is( read_file($file), "DEF", "fourth file change $desc" ); is( $output, "[tidied] foo.txt\n", "fourth output $desc" ); my $backup_dir = $ct->data_dir . "/backups"; mkpath( $backup_dir, 0, 0775 ); my @files; find( { follow => 0, wanted => sub { push @files, $_ if -f }, no_chdir => 1 }, $backup_dir ); if ($no_backups) { ok( @files == 0, "no backup files $desc" ); } else { ok( scalar(@files) == 1 || scalar(@files) == 2, "1 or 2 backup files $desc" ); foreach my $file (@files) { like( $file, qr|\.tidyall\.d/backups/foo\.txt-\d+-\d+\.bak|, "backup filename $desc" ); } } } } } sub test_selects_and_ignores : Tests { my $self = shift; my @files = ( "a/foo.pl", "b/foo.pl", "a/foo.pm", "a/bar.pm", "b/bar.pm" ); my $root_dir = $self->create_dir( { map { $_ => 'hi' } @files } ); my $ct = Code::TidyAll->new( root_dir => $root_dir, plugins => { test_plugin('UpperText') => { select => '**/*.pl **/*.pm b/bar.pm c/bar.pl', ignore => 'a/foo.pl **/bar.pm c/baz.pl' } } ); cmp_set( [ $ct->find_matched_files() ], [ "$root_dir/a/foo.pm", "$root_dir/b/foo.pl" ] ); cmp_deeply( [ map { $_->name } $ct->plugins_for_path("a/foo.pm") ], [ test_plugin('UpperText') ] ); } sub test_dirs : Tests { my $self = shift; my @files = ( "a/foo.txt", "a/bar.txt", "a/bar.pl", "b/foo.txt" ); my $root_dir = $self->create_dir( { map { $_ => 'hi' } @files } ); foreach my $recursive ( 0 .. 1 ) { my @results; my $output = capture_merged { my $ct = Code::TidyAll->new( plugins => { %UpperText, %ReverseFoo }, root_dir => $root_dir, ( $recursive ? ( recursive => 1 ) : () ) ); @results = $ct->process_paths("$root_dir/a"); }; if ($recursive) { is( @results, 3, "3 results" ); is( scalar( grep { $_->state eq 'tidied' } @results ), 2, "2 tidied" ); like( $output, qr/\[tidied\] a\/foo.txt/ ); like( $output, qr/\[tidied\] a\/bar.txt/ ); is( read_file("$root_dir/a/foo.txt"), "IH" ); is( read_file("$root_dir/a/bar.txt"), "HI" ); is( read_file("$root_dir/a/bar.pl"), "hi" ); is( read_file("$root_dir/b/foo.txt"), "hi" ); } else { is( @results, 1, "1 result" ); is( $results[0]->state, "error", "error" ); like( $output, qr/is a directory/ ); } } } sub test_errors : Tests { my $self = shift; my $root_dir = $self->create_dir( { "foo/bar.txt" => "abc" } ); throws_ok { Code::TidyAll->new( root_dir => $root_dir ) } qr/Missing required/; throws_ok { Code::TidyAll->new( plugins => {} ) } qr/Missing required/; throws_ok { Code::TidyAll->new( root_dir => $root_dir, plugins => {}, bad_param => 1, worse_param => 2 ); } qr/unknown constructor params 'bad_param', 'worse_param'/; throws_ok { Code::TidyAll->new( root_dir => $root_dir, plugins => { 'DoesNotExist' => { select => '**/*' } } )->plugin_objects; } qr/could not load plugin class/; throws_ok { Code::TidyAll->new( root_dir => $root_dir, plugins => { test_plugin('UpperText') => { select => '**/*', bad_option => 1, worse_option => 2 } } )->plugin_objects; } qr/unknown options/; my $ct = Code::TidyAll->new( plugins => {%UpperText}, root_dir => $root_dir ); my $output = capture_stdout { $ct->process_paths("$root_dir/baz/blargh.txt") }; like( $output, qr/baz\/blargh.txt: not a file or directory/, "file not found" ); $output = capture_stdout { $ct->process_paths("$root_dir/foo/bar.txt") }; is( $output, "[tidied] foo/bar.txt\n", "filename output" ); is( read_file("$root_dir/foo/bar.txt"), "ABC", "tidied" ); my $other_dir = realpath( tempdir_simple() ); write_file( "$other_dir/foo.txt", "ABC" ); throws_ok { $ct->process_paths("$other_dir/foo.txt") } qr/not underneath root dir/; } sub test_cli : Tests { my $self = shift; my $output; my @cmd = ( "$^X", "-Ilib", "bin/tidyall" ); my $run = sub { system( @cmd, @_ ) }; $output = capture_stdout { $run->("--version"); }; like( $output, qr/tidyall .* on perl/ ); $output = capture_stdout { $run->("--help"); }; like( $output, qr/Usage.*Options:/s ); foreach my $conf_name ( "tidyall.ini", ".tidyallrc" ) { my $root_dir = $self->create_dir(); my $conf_file = "$root_dir/$conf_name"; write_file( $conf_file, $cli_conf ); write_file( "$root_dir/foo.txt", "hello" ); my $output = capture_stdout { $run->( "$root_dir/foo.txt", "-v" ); }; my ($params_msg) = ( $output =~ /constructing Code::TidyAll with these params:(.*)/ ); ok( defined($params_msg), "params msg" ); like( $params_msg, qr/backup_ttl => '15m'/, 'backup_ttl' ); like( $params_msg, qr/verbose => '?1'?/, 'verbose' ); like( $params_msg, qr/\Qroot_dir => '$root_dir'\E/, 'root_dir' ); like( $output, qr/\[tidied\] foo.txt \(.*RepeatFoo, .*UpperText\)/, 'foo.txt' ); is( read_file("$root_dir/foo.txt"), "HELLOHELLOHELLO", "tidied" ); mkpath( "$root_dir/subdir", 0, 0775 ); write_file( "$root_dir/subdir/foo.txt", "bye" ); write_file( "$root_dir/subdir/foo2.txt", "bye" ); my $cwd = realpath(); capture_stdout { system("cd $root_dir/subdir; $^X -I$cwd/lib $cwd/bin/tidyall foo.txt"); }; is( read_file("$root_dir/subdir/foo.txt"), "BYEBYEBYE", "foo.txt tidied" ); is( read_file("$root_dir/subdir/foo2.txt"), "bye", "foo2.txt not tidied" ); # -p / --pipe success # my ( $stdout, $stderr ) = capture { open( my $fh, "|-", @cmd, "-p", "$root_dir/does_not_exist/foo.txt" ); print $fh "echo"; }; is( $stdout, "ECHOECHOECHO", "pipe: stdin tidied" ); unlike( $stderr, qr/\S/, "pipe: no stderr" ); # -p / --pipe error # ( $stdout, $stderr ) = capture { open( my $fh, "|-", @cmd, "--pipe", "$root_dir/foo.txt" ); print $fh "abc1"; }; is( $stdout, "abc1", "pipe: stdin mirrored to stdout" ); like( $stderr, qr/non-alpha content found/ ); } } $cli_conf = ' backup_ttl = 15m verbose = 1 [+Code::TidyAll::Test::Plugin::UpperText] select = **/*.txt [+Code::TidyAll::Test::Plugin::RepeatFoo] select = **/foo* times = 3 '; 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Conf.pm000644 777777 777777 00000000212 12217370452 022355 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705292 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Conf.pm000644 €ˆž«€q{Ì00000002722 12217370452 021342 0ustar00jonswart000000 000000 package Code::TidyAll::t::Conf; { $Code::TidyAll::t::Conf::VERSION = '0.18'; } use Code::TidyAll; use Code::TidyAll::Util qw(dirname tempdir_simple write_file); use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; my $conf1; sub test_conf_file : Tests { my $self = shift; my $root_dir = tempdir_simple(); my $conf_file = "$root_dir/tidyall.ini"; write_file( $conf_file, $conf1 ); my $ct = Code::TidyAll->new_from_conf_file($conf_file); my %expected = ( backup_ttl => '5m', backup_ttl_secs => '300', no_backups => undef, no_cache => 1, root_dir => dirname($conf_file), data_dir => "$root_dir/.tidyall.d", plugins => { '+Code::TidyAll::Test::Plugin::UpperText' => { select => '**/*.txt' }, '+Code::TidyAll::Test::Plugin::RepeatFoo' => { select => '**/foo* **/bar*', times => 3 } } ); while ( my ( $method, $value ) = each(%expected) ) { cmp_deeply( $ct->$method, $value, "$method" ); } my $conf2 = $conf1; $conf2 =~ s/times/timez/; write_file( $conf_file, $conf2 ); throws_ok { my $ct = Code::TidyAll->new_from_conf_file($conf_file)->plugin_objects } qr/unknown option 'timez'/; } $conf1 = ' backup_ttl = 5m no_cache = 1 [+Code::TidyAll::Test::Plugin::UpperText] select = **/*.txt [+Code::TidyAll::Test::Plugin::RepeatFoo] select = **/foo* select = **/bar* times = 3 '; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Git.pm000644 777777 777777 00000000212 12217370452 022213 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705293 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Git.pm000644 €ˆž«€q{Ì00000012522 12217370452 021177 0ustar00jonswart000000 000000 package Code::TidyAll::t::Git; { $Code::TidyAll::t::Git::VERSION = '0.18'; } use Capture::Tiny qw(capture_stdout capture_stderr capture); use Code::TidyAll::Git::Util qw(git_uncommitted_files); use Code::TidyAll::Util qw(dirname mkpath pushd read_file realpath tempdir_simple write_file); use Code::TidyAll; use IPC::System::Simple qw(capturex run); use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; my ( $precommit_hook_template, $prereceive_hook_template, $tidyall_ini_template ); sub test_git : Tests { my ($self) = @_; my $temp_dir = tempdir_simple; my $work_dir = "$temp_dir/work"; my $hooks_dir = "$work_dir/.git/hooks"; my $output; my $committed = sub { like( capturex( 'git', 'status' ), qr/nothing to commit/, "committed" ); }; my $uncommitted = sub { unlike( capturex( 'git', 'status' ), qr/nothing to commit/, "committed" ); }; my $pushed = sub { unlike( capturex( 'git', 'status' ), qr/Your branch is ahead/, "pushed" ); }; my $unpushed = sub { like( capturex( 'git', 'status' ), qr/Your branch is ahead/, "unpushed" ); }; # Create the repo # run( "git", "init", $work_dir ); ok( -d $_, "$_ exists" ) for ( $work_dir, $hooks_dir ); my $pushd = pushd($work_dir); # Add tidyall.ini and .gitignore # write_file( "$work_dir/tidyall.ini", sprintf($tidyall_ini_template) ); write_file( "$work_dir/.gitignore", ".tidyall.d" ); run( "git", "add", "tidyall.ini", ".gitignore" ); run( "git", "commit", "-m", "added", "tidyall.ini", ".gitignore" ); # Add foo.txt, which needs tidying # write_file( "$work_dir/foo.txt", "abc\n" ); cmp_deeply( [ git_uncommitted_files($work_dir) ], [], "no uncommitted files" ); # git add foo.txt and make sure it is now in uncommitted list # run( "git", "add", "foo.txt" ); cmp_deeply( [ git_uncommitted_files($work_dir) ], ["$work_dir/foo.txt"], "one uncommitted file" ); # Add pre-commit hook # my $precommit_hook_file = "$hooks_dir/pre-commit"; my $precommit_hook = sprintf( $precommit_hook_template, realpath("lib") ); write_file( $precommit_hook_file, $precommit_hook ); chmod( 0775, $precommit_hook_file ); # Try to commit, make sure we get error # $output = capture_stderr { system( "git", "commit", "-m", "changed", "-a" ) }; like( $output, qr/1 file did not pass tidyall check/, "1 file did not pass tidyall check" ); like( $output, qr/needs tidying/, "needs tidying" ); $uncommitted->(); # Fix file and commit successfully # write_file( "$work_dir/foo.txt", "ABC\n" ); $output = capture_stderr { run( "git", "commit", "-m", "changed", "-a" ) }; like( $output, qr/\[checked\] foo\.txt/, "checked foo.txt" ); $committed->(); # Create a bare shared repo, then a clone of that # my $shared_dir = "$temp_dir/shared"; my $clone_dir = "$temp_dir/clone"; run( "git", "clone", "--bare", $work_dir, $shared_dir ); run( "git", "clone", $shared_dir, $clone_dir ); chdir($clone_dir); $committed->(); # Add prereceive hook to shared repo # my $prereceive_hook_file = "$shared_dir/hooks/pre-receive"; my $prereceive_hook = sprintf( $prereceive_hook_template, realpath("lib") ); write_file( $prereceive_hook_file, $prereceive_hook ); chmod( 0775, $prereceive_hook_file ); # Unfix file and commit # write_file( "$clone_dir/foo.txt", "def\n" ); run( "git", "commit", "-m", "changed", "-a" ); $committed->(); # Try to push, make sure we get error back # $unpushed->(); $output = capture_stderr { system( "git", "push" ) }; like( $output, qr/master -> master/, "master -> master" ); like( $output, qr/1 file did not pass tidyall check/, "1 file did not pass tidyall check" ); like( $output, qr/needs tidying/, "needs tidying" ); $unpushed->(); # Fix file and push successfully # write_file( "$clone_dir/foo.txt", "DEF\n" ); $output = capture_stderr { run( "git", "commit", "-m", "changed", "-a" ) }; $committed->(); $output = capture_stderr { system( "git", "push" ) }; like( $output, qr/master -> master/, "master -> master" ); $pushed->(); # Unfix file and commit # write_file( "$clone_dir/foo.txt", "def\n" ); run( "git", "commit", "-m", "changed", "-a" ); $committed->(); # Try #1: make sure we get error back # $unpushed->(); $output = capture_stderr { system( "git", "push" ) }; like( $output, qr/needs tidying/, "needs tidying" ); $unpushed->(); # Try #2: make sure we get error and repeat notification back # $unpushed->(); $output = capture_stderr { system( "git", "push" ) }; like( $output, qr/needs tidying/, "needs tidying" ); like( $output, qr/Identical push seen 2 times/, "Identical push seen 2 times" ); $unpushed->(); } $precommit_hook_template = '#!/usr/bin/perl use lib qw(%s); use Code::TidyAll::Git::Precommit; use strict; use warnings; Code::TidyAll::Git::Precommit->check( tidyall_options => { verbose => 1 } ); '; $prereceive_hook_template = '#!/usr/bin/perl use lib qw(%s); use Code::TidyAll::Git::Prereceive; use strict; use warnings; Code::TidyAll::Git::Prereceive->check(); '; $tidyall_ini_template = ' [+Code::TidyAll::Test::Plugin::UpperText] select = **/*.txt '; 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Plugin000775 777777 777777 00000000213 12217370452 022321 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705298 19 SCHILY.nlink=14 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/000775 €ˆž«€q{Ì00000000000 12217370452 021354 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Plugin.pm000644 777777 777777 00000000212 12217370452 022726 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705294 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin.pm000644 €ˆž«€q{Ì00000003773 12217370452 021722 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin; { $Code::TidyAll::t::Plugin::VERSION = '0.18'; } use Capture::Tiny qw(capture); use Code::TidyAll::Util qw(tempdir_simple); use Code::TidyAll; use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; __PACKAGE__->SKIP_CLASS("Virtual base class"); my $Test = Test::Builder->new; sub startup : Tests(startup => no_plan) { my $self = shift; $self->{root_dir} = tempdir_simple(); } sub plugin_class { my ($self) = @_; return ( split( '::', ref($self) ) )[-1]; } sub test_filename { 'foo.txt' } sub tidyall { my ( $self, %p ) = @_; my $source = $p{source} || die "source required"; my $desc = $p{desc} || $source; $desc =~ s/\n/\\n/g; my $plugin_class = $self->plugin_class; my %plugin_conf = ( $plugin_class => { select => '*', %{ $p{conf} || {} } } ); my $ct = Code::TidyAll->new( quiet => 1, root_dir => $self->{root_dir}, plugins => \%plugin_conf ); $source =~ s/\\n/\n/g; my $result; my ( $output, $error ) = capture { $result = $ct->process_source( $source, $self->test_filename ) }; $Test->diag($output) if $output && $ENV{TEST_VERBOSE}; $Test->diag($error) if $error && $ENV{TEST_VERBOSE}; if ( my $expect_tidy = $p{expect_tidy} ) { $expect_tidy =~ s/\\n/\n/g; is( $result->state, 'tidied', "state=tidied [$desc]" ); is( $result->new_contents, $expect_tidy, "new contents [$desc]" ); is( $result->error, undef, "no error [$desc]" ); } elsif ( my $expect_ok = $p{expect_ok} ) { is( $result->state, 'checked', "state=checked [$desc]" ); is( $result->error, undef, "no error [$desc]" ); if ( $result->new_contents ) { is( $result->new_contents, $source, "same contents [$desc]" ); } } elsif ( my $expect_error = $p{expect_error} ) { is( $result->state, 'error', "state=error [$desc]" ); like( $result->error || '', $expect_error, "error message [$desc]" ); } } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/SVN.pm000644 777777 777777 00000000212 12217370452 022136 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705295 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/SVN.pm000644 €ˆž«€q{Ì00000010272 12217370452 021122 0ustar00jonswart000000 000000 package Code::TidyAll::t::SVN; { $Code::TidyAll::t::SVN::VERSION = '0.18'; } use Capture::Tiny qw(capture_stdout capture_stderr capture); use Code::TidyAll::SVN::Precommit; use Code::TidyAll::SVN::Util qw(svn_uncommitted_files); use Code::TidyAll::Util qw(dirname mkpath read_file realpath tempdir_simple write_file); use Code::TidyAll; use IPC::System::Simple qw(run); use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; my ( $precommit_hook_template, $tidyall_ini_template ); sub test_svn : Tests { my ($self) = @_; my $temp_dir = tempdir_simple; my $repo_dir = "$temp_dir/repo"; my $src_dir = "$temp_dir/src"; my $work_dir = "$temp_dir/work"; my $hook_log = "$temp_dir/hook.log"; my ( $stdout, $stderr ); my $log_contains = sub { my $regex = shift; like( read_file($hook_log), $regex ); }; my $clear_log = sub { run("cat /dev/null > $hook_log"); }; my $committed = sub { $stdout = capture_stdout { system( sprintf( 'svn status %s', $work_dir ) ) }; unlike( $stdout, qr/\S/, "committed" ); }; my $uncommitted = sub { $stdout = capture_stdout { system( sprintf( 'svn status %s', $work_dir ) ) }; like( $stdout, qr/^M/, "uncommitted" ); }; run("svnadmin create $repo_dir"); my $hooks_dir = "$repo_dir/hooks"; ok( -d $hooks_dir, "$hooks_dir exists" ); mkpath( $src_dir, 0, 0775 ); write_file( "$src_dir/foo.txt", "abc" ); run( sprintf( 'svn -q import %s file://%s/myapp/trunk -m "import"', $src_dir, $repo_dir ) ); run( sprintf( 'svn -q checkout file://%s/myapp/trunk %s', $repo_dir, $work_dir ) ); is( read_file("$work_dir/foo.txt"), "abc", "checkout and import ok" ); cmp_deeply( [ svn_uncommitted_files($work_dir) ], [], "no uncommitted files" ); my $precommit_hook_file = "$hooks_dir/pre-commit"; my $precommit_hook = sprintf( $precommit_hook_template, realpath("lib"), $hook_log ); write_file( $precommit_hook_file, $precommit_hook ); chmod( 0775, $precommit_hook_file ); write_file( "$work_dir/foo.txt", "abc " ); mkpath( "$work_dir/bar", 0, 0775 ); run( sprintf( 'svn add %s/bar', $work_dir ) ); cmp_deeply( [ svn_uncommitted_files($work_dir) ], [ re("foo.txt") ], "one uncommitted file" ); $stderr = capture_stderr { run( sprintf( 'svn -q commit -m "changed" %s/foo.txt %s/bar', $work_dir, $work_dir ) ); }; unlike( $stderr, qr/\S/ ); $log_contains->(qr|could not find.*upwards from 'myapp/trunk/foo.txt'|); $clear_log->(); $committed->(); cmp_deeply( [ svn_uncommitted_files($work_dir) ], [], "no uncommitted files" ); write_file( "$work_dir/tidyall.ini", sprintf($tidyall_ini_template) ); run( sprintf( 'svn -q add %s/tidyall.ini', $work_dir ) ); cmp_deeply( [ svn_uncommitted_files($work_dir) ], [ re("tidyall.ini") ], "one uncommitted file" ); run( sprintf( 'svn -q commit -m "added" %s/tidyall.ini', $work_dir ) ); write_file( "$work_dir/foo.txt", "abc" ); $stderr = capture_stderr { system( sprintf( 'svn -q commit -m "changed" %s/foo.txt', $work_dir ) ) }; like( $stderr, qr/1 file did not pass tidyall check/ ); like( $stderr, qr/needs tidying/ ); $uncommitted->(); write_file( "$work_dir/foo.txt", "ABC" ); write_file( "$work_dir/bar.dat", "123" ); run( sprintf( 'svn -q add %s/bar.dat', $work_dir ) ); $stderr = capture_stderr { system( sprintf( 'svn -q commit -m "changed" %s/foo.txt %s/bar.dat', $work_dir, $work_dir ) ); }; unlike( $stderr, qr/\S/ ); $committed->(); write_file( "$work_dir/foo.txt", "def" ); $stderr = capture_stderr { system( sprintf( 'svn -q commit -m "NO TIDYALL - emergency fix!" %s/foo.txt', $work_dir ) ); }; unlike( $stderr, qr/\S/ ); $committed->(); } $precommit_hook_template = '#!/usr/bin/perl use lib qw(%s); use Code::TidyAll::SVN::Precommit; use Log::Any::Adapter (File => "%s"); use strict; use warnings; Code::TidyAll::SVN::Precommit->check( extra_conf_files => ["perlcriticrc"], tidyall_options => { verbose => 1 } ); '; $tidyall_ini_template = ' [+Code::TidyAll::Test::Plugin::UpperText] select = **/*.txt '; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Util.pm000644 777777 777777 00000000212 12217370452 022405 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705296 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Util.pm000644 €ˆž«€q{Ì00000001011 12217370452 021360 0ustar00jonswart000000 000000 package Code::TidyAll::t::Util; { $Code::TidyAll::t::Util::VERSION = '0.18'; } use Code::TidyAll::Util qw(dirname tempdir_simple); use IPC::System::Simple qw(capturex); use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; sub test_tempdir_simple : Tests { my $dir = capturex( "$^X", "-I", "lib", "-MCode::TidyAll::Util", "-e", "print Code::TidyAll::Util::tempdir_simple " ); ok( -d dirname($dir), "parent exists" ); ok( !-d $dir, "dir does not exist" ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/PaxHeader/Zglob.pm000644 777777 777777 00000000212 12217370452 022545 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705297 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Zglob.pm000644 €ˆž«€q{Ì00000002076 12217370452 021534 0ustar00jonswart000000 000000 package Code::TidyAll::t::Zglob; { $Code::TidyAll::t::Zglob::VERSION = '0.18'; } use File::Zglob; use Test::Class::Most parent => 'Code::TidyAll::Test::Class'; use Code::TidyAll::Util::Zglob qw(zglob_to_regex); sub test_match : Tests { my ( $zglob, $regex ); $zglob = "**/*.txt"; $regex = zglob_to_regex($zglob); foreach my $path (qw(foo.txt foo/baz.txt foo/bar/baz.txt)) { like( $path, $regex, "$path matches $zglob" ); } foreach my $path (qw(foo/bar/baz.tx)) { unlike( $path, $regex, "$path does not match $zglob" ); } $zglob = "**/*"; $regex = zglob_to_regex($zglob); foreach my $path (qw(foo foo.txt foo/bar foo/baz.txt)) { like( $path, $regex, "$path matches $zglob" ); } $zglob = "foo/**/*.txt"; $regex = zglob_to_regex($zglob); foreach my $path (qw(foo/baz.txt foo/bar/baz.txt foo/bar/baz/blargh.txt)) { like( $path, $regex, "$path matches $zglob" ); } foreach my $path (qw(foo.txt foo/bar/baz.tx)) { unlike( $path, $regex, "$path does not match $zglob" ); } } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/CSSUnminifier.pm000644 777777 777777 00000000212 12217370452 025404 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705299 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/CSSUnminifier.pm000644 €ˆž«€q{Ì00000001171 12217370452 024366 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::CSSUnminifier; { $Code::TidyAll::t::Plugin::CSSUnminifier::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; my $source = 'body {\nfont-family:helvetica;\nfont-size:15pt;\n}'; $self->tidyall( source => $source, expect_tidy => 'body {\n font-family: helvetica;\n font-size: 15pt;\n}\n' ); $self->tidyall( source => $source, conf => { argv => '-w=2' }, expect_tidy => 'body {\n font-family: helvetica;\n font-size: 15pt;\n}\n' ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/JSBeautify.pm000644 777777 777777 00000000212 12217370452 024733 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705300 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/JSBeautify.pm000644 €ˆž«€q{Ì00000001164 12217370452 023717 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::JSBeautify; { $Code::TidyAll::t::Plugin::JSBeautify::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; my $source = 'sp.toggleResult=function(id){foo(id)}'; $self->tidyall( source => $source, expect_tidy => 'sp.toggleResult = function(id) {\n foo(id)\n}\n', ); $self->tidyall( source => $source, conf => { argv => '--indent-size 3 --brace-style expand' }, expect_tidy => 'sp.toggleResult = function(id)\n{\n foo(id)\n}\n', ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/JSHint.pm000644 777777 777777 00000000212 12217370452 024065 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705301 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/JSHint.pm000644 €ˆž«€q{Ì00000003765 12217370452 023062 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::JSHint; { $Code::TidyAll::t::Plugin::JSHint::VERSION = '0.18'; } use Code::TidyAll::Util qw(write_file); use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_filename { 'foo.js' } sub test_main : Tests { my $self = shift; my $rc_file = $self->{root_dir} . "/jshint.json"; $self->tidyall( source => 'var my_object = {};', expect_ok => 1, desc => 'ok - camelcase', ); $self->tidyall( source => 'while (day)\n shuffle();', expect_ok => 1, desc => 'ok no brace', ); $self->tidyall( source => 'var my_object = new Object();', expect_error => qr/object literal notation/, desc => 'error - object literal', ); $self->tidyall( source => 'var my_object = {};', conf => { options => 'camelcase' }, expect_error => qr/not in camel case/, desc => 'error - camel case - options=camelcase', ); $self->tidyall( source => 'var my_object = {};', conf => { options => 'camelcase curly' }, expect_error => qr/not in camel case/, desc => 'error - camel case - options=camelcase,curly', ); $self->tidyall( source => 'while (day)\n shuffle();', conf => { options => 'camelcase curly' }, expect_error => qr/Expected \'{/, desc => 'error - curly - options=camelcase,curly', ); write_file( $rc_file, '{"camelcase": true}' ); $self->tidyall( source => 'var my_object = {};', conf => { argv => "--config $rc_file" }, expect_error => qr/not in camel case/, desc => 'error - camelcase - conf file', ); $self->tidyall( source => 'var my_object = {};', conf => { argv => "--badoption" }, expect_error => qr/Unknown option/, desc => 'error - bad option' ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/JSLint.pm000644 777777 777777 00000000212 12217370452 024071 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705302 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/JSLint.pm000644 €ˆž«€q{Ì00000001756 12217370452 023064 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::JSLint; { $Code::TidyAll::t::Plugin::JSLint::VERSION = '0.18'; } use Code::TidyAll::Util qw(write_file); use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_filename { 'foo.js' } sub test_main : Tests { my $self = shift; $self->tidyall( source => 'var my_object = {};', expect_ok => 1, desc => 'ok', ); $self->tidyall( source => 'while (true) {\nvar i = 5;\n}', expect_error => qr/Expected 'var' at column 5/, desc => 'error - bad indentation' ); $self->tidyall( source => 'while (true) {\nvar i = 5;\n}', conf => { argv => '--white' }, expect_ok => 1, desc => 'ok - bad indentation, --white' ); $self->tidyall( source => 'var my_object = {};', conf => { argv => '--badoption' }, expect_error => qr/Usage/, desc => 'error - bad option' ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/MasonTidy.pm000644 777777 777777 00000000212 12217370452 024635 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705303 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/MasonTidy.pm000644 €ˆž«€q{Ì00000001726 12217370452 023625 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::MasonTidy; { $Code::TidyAll::t::Plugin::MasonTidy::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; my $source; $source = '%if($foo) {\n%bar(1,2);\n%}'; $self->tidyall( source => $source, conf => { argv => '-m 1' }, expect_tidy => '% if ($foo) {\n% bar( 1, 2 );\n% }' ); $self->tidyall( source => $source, conf => { argv => '-m 1 --perltidy-argv="-pt=2 -i=3"' }, expect_tidy => '% if ($foo) {\n% bar(1, 2);\n% }' ); $self->tidyall( source => $source, conf => { argv => '-m 2 --perltidy-line-argv=" "' }, expect_tidy => '% if ($foo) {\n% bar( 1, 2 );\n% }' ); $self->tidyall( source => $source, conf => { argv => '-m 1 --badoption' }, expect_error => qr/Usage/ ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/PerlCritic.pm000644 777777 777777 00000000212 12217370452 024766 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705304 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PerlCritic.pm000644 €ˆž«€q{Ì00000002625 12217370452 023755 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::PerlCritic; { $Code::TidyAll::t::Plugin::PerlCritic::VERSION = '0.18'; } use Code::TidyAll::Util qw(write_file); use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; my $rc_file = $self->{root_dir} . "/perlcriticrc"; write_file( $rc_file, "only = 1\nseverity = 1\n[TestingAndDebugging::RequireUseStrict]\n" ); $self->tidyall( source => 'my $foo = 5\n', conf => { argv => "--profile $rc_file" }, expect_error => qr/Code before strictures/, ); $self->tidyall( source => 'use strict;\nuse warnings;\nmy $foo = 5\n', conf => { argv => "--profile $rc_file" }, expect_ok => 1, ); write_file( $rc_file, "only = 1\nseverity = 1\n[CodeLayout::ProhibitHardTabs]\n" ); $self->tidyall( source => 'my $foo = 5\n', conf => { argv => "--profile $rc_file" }, expect_ok => 1, ); $self->tidyall( source => 'my $foo = 5\n', conf => { argv => "--profile $rc_file --badoption" }, expect_error => qr/Unknown option: badoption/ ); write_file( $rc_file, "badconfig = 1\n" ); $self->tidyall( source => 'my $foo = 5\n', conf => { argv => "--profile $rc_file" }, expect_error => qr/"badconfig" is not a supported option/ ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/PerlTidy.pm000644 777777 777777 00000000212 12217370452 024462 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705305 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PerlTidy.pm000644 €ˆž«€q{Ì00000001723 12217370452 023447 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::PerlTidy; { $Code::TidyAll::t::Plugin::PerlTidy::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; my $source = 'if ( $foo) {\nmy $bar = $baz;\n}\n'; $self->tidyall( source => $source, expect_tidy => 'if ($foo) {\n my $bar = $baz;\n}\n' ); $self->tidyall( conf => { argv => '-bl' }, source => $source, expect_tidy => 'if ($foo)\n{\n my $bar = $baz;\n}\n' ); $self->tidyall( source => 'if ($foo) {\n my $bar = $baz;\n}\n', expect_ok => 1 ); $self->tidyall( source => 'if ($foo) {\n my $bar = $baz;\n', expect_error => qr/Final nesting depth/ ); $self->tidyall( conf => { argv => '--badoption' }, source => $source, expect_error => qr/Unknown option: badoption/ ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/PHPCodeSniffer.pm000644 777777 777777 00000000212 12217370452 025465 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705306 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PHPCodeSniffer.pm000644 €ˆž«€q{Ì00000001513 12217370452 024447 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::PHPCodeSniffer; { $Code::TidyAll::t::Plugin::PHPCodeSniffer::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_filename { 'foo.php' } sub test_main : Tests { my $self = shift; my $cmd = '/usr/local/pear/bin/phpcs'; my $source = ''; $self->tidyall( source => $source, conf => { cmd => $cmd, argv => "--severity=6" }, expect_ok => 1, ); $self->tidyall( source => $source, conf => { cmd => $cmd, argv => "--severity=3" }, expect_error => qr/Missing .* doc/, ); $self->tidyall( source => $source, conf => { cmd => $cmd, argv => "--blahblah" }, expect_error => qr/not known/, ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/PodChecker.pm000644 777777 777777 00000000212 12217370452 024735 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705307 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PodChecker.pm000644 €ˆž«€q{Ì00000003464 12217370452 023726 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::PodChecker; { $Code::TidyAll::t::Plugin::PodChecker::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; $self->tidyall( source => '=head1 DESCRIPTION\n\nHello', expect_ok => 1, desc => 'ok', ); $self->tidyall( source => '=head1 METHODS\n\n=over', expect_error => qr/without closing =back/, desc => 'error', ); $self->tidyall( source => '=head1 DESCRIPTION\n\n=head1 METHODS\n\n', expect_ok => 1, desc => 'ok - empty section, no warnings', ); $self->tidyall( source => '=head1 DESCRIPTION\n\n=head1 METHODS\n\n', conf => { warnings => 1 }, expect_error => qr/empty section in previous paragraph/, desc => 'error - empty section, warnings=1', ); $self->tidyall( source => '=head1 DESCRIPTION\n\nblah blah\n\n=head1 DESCRIPTION\n\nblah blah', conf => { warnings => 1 }, expect_ok => 1, desc => 'ok - duplicate section, warnings=1', ); $self->tidyall( source => '=head1 DESCRIPTION\n\nblah blah\n\n=head1 DESCRIPTION\n\nblah blah', conf => { warnings => 2 }, expect_error => qr/multiple occurrence/, desc => 'error - duplicate section, warnings=2', ); } 1; __END__ =pod =head1 VERSION version 0.18 =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/PodSpell.pm000644 777777 777777 00000000212 12217370452 024450 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705308 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PodSpell.pm000644 €ˆž«€q{Ì00000002570 12217370452 023436 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::PodSpell; { $Code::TidyAll::t::Plugin::PodSpell::VERSION = '0.18'; } use Code::TidyAll::Util qw(write_file); use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_filename { 'Foo.pod' } sub test_main : Tests { my $self = shift; my $dict_file = $self->{root_dir} . "/.ispell_english"; $self->tidyall( source => '=head SUMMARY\n\nthe quick brown fox jumped over the lazy dogs', expect_ok => 1, desc => 'ok', ); $self->tidyall( source => '=head SUMMARY\n\nthe quick browwn fox jumped over the lazeey dogs', expect_error => qr/unrecognized words:\nbrowwn\nlazeey/, desc => 'spelling mistakes', ); write_file( $dict_file, "browwn\n" ); $self->tidyall( source => '=head SUMMARY\n\nthe quick browwn fox jumped over the lazeey dogs', conf => { ispell_argv => "-p $dict_file" }, expect_error => qr/unrecognized words:\nlazeey/, desc => 'spelling mistakes, one in dictionary', ); write_file( $dict_file, "browwn\nlazeey\n" ); $self->tidyall( source => '=head SUMMARY\n\nthe quick browwn fox jumped over the lazeey dogs', conf => { ispell_argv => "-p $dict_file" }, expect_ok => 1, desc => 'spelling mistakes, all in dictionary', ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/PodTidy.pm000644 777777 777777 00000000212 12217370452 024302 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705309 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PodTidy.pm000644 €ˆž«€q{Ì00000005251 12217370452 023267 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::PodTidy; { $Code::TidyAll::t::Plugin::PodTidy::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; my $source = '=head1 DESCRIPTION There are a lot of great code tidiers and validators out there. C makes them available from a single unified interface. You can run C on a single file or on an entire project hierarchy, and configure which tidiers/validators are applied to which files. C will back up files beforehand, and for efficiency will only consider files that have changed since they were last processed. '; $self->tidyall( source => $source, expect_tidy => '=head1 DESCRIPTION There are a lot of great code tidiers and validators out there. C makes them available from a single unified interface. You can run C on a single file or on an entire project hierarchy, and configure which tidiers/validators are applied to which files. C will back up files beforehand, and for efficiency will only consider files that have changed since they were last processed. ', desc => 'tidy - defaults', ); $self->tidyall( source => '=head1 DESCRIPTION There are a lot of great code tidiers and validators out there. C makes them available from a single unified interface. You can run C on a single file or on an entire project hierarchy, and configure which tidiers/validators are applied to which files. C will back up files beforehand, and for efficiency will only consider files that have changed since they were last processed. ', expect_ok => 1, desc => 'ok - defaults', ); $self->tidyall( source => $source, conf => { columns => 30 }, expect_tidy => '=head1 DESCRIPTION There are a lot of great code tidiers and validators out there. C makes them available from a single unified interface. You can run C on a single file or on an entire project hierarchy, and configure which tidiers/validators are applied to which files. C will back up files beforehand, and for efficiency will only consider files that have changed since they were last processed. ', desc => 'tidy - columns = 30', ); } 1; __END__ =pod =head1 VERSION version 0.18 =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/PaxHeader/SortLines.pm000644 777777 777777 00000000212 12217370452 024650 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705310 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/t/Plugin/SortLines.pm000644 €ˆž«€q{Ì00000000555 12217370452 023637 0ustar00jonswart000000 000000 package Code::TidyAll::t::Plugin::SortLines; { $Code::TidyAll::t::Plugin::SortLines::VERSION = '0.18'; } use Test::Class::Most parent => 'Code::TidyAll::t::Plugin'; sub test_main : Tests { my $self = shift; $self->tidyall( source => "c\nb\na\n", expect_tidy => "a\nb\nc\n" ); $self->tidyall( source => "\n\na\n\n\n", expect_tidy => "a\n" ); } 1; Code-TidyAll-0.18/lib/Code/TidyAll/SVN/PaxHeader/Precommit.pm000644 777777 777777 00000000212 12217370452 023632 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705288 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/SVN/Precommit.pm000644 €ˆž«€q{Ì00000023254 12217370452 022622 0ustar00jonswart000000 000000 package Code::TidyAll::SVN::Precommit; { $Code::TidyAll::SVN::Precommit::VERSION = '0.18'; } use Capture::Tiny qw(capture_stdout capture_stderr); use Code::TidyAll; use Code::TidyAll::Util qw(basename dirname mkpath realpath tempdir_simple write_file); use Log::Any qw($log); use Moo; use SVN::Look; use Try::Tiny; # Public has 'conf_name' => ( is => 'ro' ); has 'emergency_comment_prefix' => ( is => 'ro', default => sub { "NO TIDYALL" } ); has 'extra_conf_files' => ( is => 'ro', default => sub { [] } ); has 'reject_on_error' => ( is => 'ro' ); has 'repos' => ( is => 'ro', default => sub { $ARGV[0] } ); has 'tidyall_class' => ( is => 'ro', default => sub { "Code::TidyAll" } ); has 'tidyall_options' => ( is => 'ro', default => sub { {} } ); has 'txn' => ( is => 'ro', default => sub { $ARGV[1] } ); # Private has 'cat_file_cache' => ( init_arg => undef, is => 'ro', default => sub { {} } ); has 'revlook' => ( init_arg => undef, is => 'lazy' ); sub _build_revlook { my $self = shift; return SVN::Look->new( $self->repos, '-t' => $self->txn ); } sub check { my ( $class, %params ) = @_; my $fail_msg; try { my $self = $class->new(%params); my $revlook = $self->revlook; # Skip if emergency comment prefix is present # if ( my $prefix = $self->emergency_comment_prefix ) { if ( index( $revlook->log_msg, $prefix ) == 0 ) { return; } } my @files = ( $self->revlook->added(), $self->revlook->updated() ); $log->info("----------------------------"); $log->infof( "%s [%s] repos = %s; txn = %s", scalar(localtime), $$, scalar( getpwuid($<) ), $self->repos, $self->txn ); $log->infof( "looking at files: %s", join( ", ", @files ) ); my %conf_files; foreach my $file (@files) { if ( my $conf_file = $self->find_conf_for_file($file) ) { my $root = dirname($conf_file); my $rel_file = substr( $file, length($root) + 1 ); $conf_files{$conf_file}->{$rel_file}++; } else { my $msg = sprintf( "** could not find conf file upwards from '%s'", $file ); $log->error($msg); die $msg if $self->reject_on_error; } } my @results; while ( my ( $conf_file, $file_map ) = each(%conf_files) ) { my $root = dirname($conf_file); my $conf_name = basename($conf_file); $log->error("$root, $conf_file"); my $tempdir = tempdir_simple(); my @files = keys(%$file_map); foreach my $rel_file ( $conf_name, @{ $self->extra_conf_files }, @files ) { # TODO: what if cat fails my $contents = $self->cat_file("$root/$rel_file"); my $full_path = "$tempdir/$rel_file"; mkpath( dirname($full_path), 0, 0775 ); write_file( $full_path, $contents ); } my $tidyall = $self->tidyall_class->new_from_conf_file( join( "/", $tempdir, $conf_name ), no_cache => 1, check_only => 1, mode => 'commit', %{ $self->tidyall_options }, ); my $stdout = capture_stdout { push( @results, $tidyall->process_paths( map { "$tempdir/$_" } @files ) ); }; if ($stdout) { chomp($stdout); $log->info($stdout); } } if ( my @error_results = grep { $_->error } @results ) { my $error_count = scalar(@error_results); $fail_msg = join( "\n", sprintf( "%d file%s did not pass tidyall check", $error_count, $error_count > 1 ? "s" : "" ), map { join( ": ", $_->path, $_->error ) } @error_results ); } } catch { my $error = $_; $log->error($error); die $error if $params{reject_on_error}; }; die $fail_msg if $fail_msg; } sub find_conf_for_file { my ( $self, $file ) = @_; my @conf_names = $self->conf_name ? ( $self->conf_name ) : Code::TidyAll->default_conf_names; my $search_dir = dirname($file); $search_dir =~ s{/+$}{}; my $cnt = 0; while (1) { foreach my $conf_name (@conf_names) { my $conf_file = "$search_dir/$conf_name"; return $conf_file if ( $self->cat_file($conf_file) ); } if ( $search_dir eq '/' || $search_dir eq '' || $search_dir eq '.' ) { return undef; } else { $search_dir = dirname($search_dir); } die "inf loop!" if ++$cnt > 100; } } sub cat_file { my ( $self, $file ) = @_; my $contents; if ( exists( $self->cat_file_cache->{$file} ) ) { $contents = $self->cat_file_cache->{$file}; } else { try { capture_stderr { $contents = $self->revlook->cat($file) }; } catch { $contents = ''; }; $self->cat_file_cache->{$file} = $contents; } return $contents; } 1; __END__ =pod =head1 NAME Code::TidyAll::SVN::Precommit - Subversion pre-commit hook that requires files to be tidyall'd =head1 VERSION version 0.18 =head1 SYNOPSIS In hooks/pre-commit in your svn repo: #!/usr/bin/perl use Code::TidyAll::SVN::Precommit; use Log::Any::Adapter (File => "/path/to/hooks/logs/tidyall.log"); use strict; use warnings; Code::TidyAll::SVN::Precommit->check(); =head1 DESCRIPTION This module implements a L that checks if all files are tidied and valid according to L, and rejects the commit if not. =head1 METHODS =over =item check (key/value params...) Class method. Check that all files being added or modified in this commit are tidied and valid according to L. If not, then the entire commit is rejected and the reason(s) are output to the client. e.g. % svn commit -m "fixups" CHI.pm CHI/Driver.pm Sending CHI/Driver.pm Sending CHI.pm Transmitting file data ..svn: Commit failed (details follow): svn: Commit blocked by pre-commit hook (exit code 255) with output: 2 files did not pass tidyall check lib/CHI.pm: *** 'PerlTidy': needs tidying lib/CHI/Driver.pm: *** 'PerlCritic': Code before strictures are enabled at /tmp/Code-TidyAll-0e6K/Driver.pm line 2 [TestingAndDebugging::RequireUseStrict] In an emergency the hook can be bypassed by prefixing the comment with "NO TIDYALL", e.g. % svn commit -m "NO TIDYALL - this is an emergency!" CHI.pm CHI/Driver.pm Sending CHI/Driver.pm Sending CHI.pm Transmitting file data . Committed revision 7562. The configuration file (C or C<.tidyallrc>) must be checked into svn. For each file, the hook will look upwards from the file's repo location and use the first configuration file it finds. By default, if the configuration file cannot be found, or if a runtime error occurs, a warning is logged (see L below) but the commit is allowed to proceed. This is so that unexpected problems do not prevent valid commits. Passes mode = "commit" by default; see L. Key/value parameters: =over =item conf_name Conf file name to search for instead of the defaults. =item emergency_comment_prefix Commit prefix that will cause this hook to be bypassed. Defaults to "NO TIDYALL". e.g. svn commit -m "NO TIDYALL - must get fix to production!" Set to a false value (e.g. blank or undefined) to disable bypassing. =item extra_conf_files A listref of other configuration files referred to from the main configuration file, e.g. extra_conf_files => ['perlcriticrc', 'perltidyrc'] If you don't list them here then you'll get errors like 'cannot find perlcriticrc' when the hook runs. =item reject_on_error If the configuration file cannot be found for some/all the files, or if a runtime error occurs, reject the commit. =item repos Repository path being committed; defaults to C<< $ARGV[0] >> =item tidyall_class Subclass to use instead of L =item tidyall_options Hashref of options to pass to the L constructor =item txn Commit transaction; defaults to C<< $ARGV[1] >> =back =back =head1 LOGGING This module uses L to log its activity, including all files that were checked, an inability to find the configuration file, and any runtime errors that occur. You can create a simple date-stamped log file with use Log::Any::Adapter (File => "/path/to/hooks/logs/tidyall.log"); or do something fancier with one of the other L. Having a log file is especially useful with pre-commit hooks since there is no way for the hook to send back output on a successful commit. =head1 ACKNOWLEDGMENTS Thanks to Alexander Simakov, author of L, for some of the ideas here such as emergency_comment_prefix. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/SVN/PaxHeader/Util.pm000644 777777 777777 00000000212 12217370452 022610 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705289 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/SVN/Util.pm000644 €ˆž«€q{Ì00000001003 12217370452 021564 0ustar00jonswart000000 000000 package Code::TidyAll::SVN::Util; { $Code::TidyAll::SVN::Util::VERSION = '0.18'; } use Cwd qw(realpath); use IPC::System::Simple qw(capturex); use strict; use warnings; use base qw(Exporter); our @EXPORT_OK = qw(svn_uncommitted_files); sub svn_uncommitted_files { my ($dir) = @_; $dir = realpath($dir); my $output = capturex( "svn", "status", $dir ); my @lines = grep { /^[AM]/ } split( "\n", $output ); my (@files) = grep { -f } ( $output =~ m{^[AM]\s+(.*)$}gm ); return @files; } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/CSSUnminifier.pm000644 777777 777777 00000000212 12217370452 025141 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705275 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/CSSUnminifier.pm000644 €ˆž«€q{Ì00000002306 12217370452 024124 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::CSSUnminifier; { $Code::TidyAll::Plugin::CSSUnminifier::VERSION = '0.18'; } use IPC::System::Simple qw(run); use Moo; extends 'Code::TidyAll::Plugin'; sub _build_cmd { 'cssunminifier' } sub transform_file { my ( $self, $file ) = @_; run( $self->cmd, $self->argv, $file, $file ); } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::CSUnminifier - use cssunminifier with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [CSSUnminifier] select = static/**/*.css argv = -w=2 =head1 DESCRIPTION Runs L, a simple CSS tidier. =head1 INSTALLATION Install L, then run npm install cssunminifier -g =head1 CONFIGURATION =over =item argv Arguments to pass to C =item cmd Full path to C =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/JSBeautify.pm000644 777777 777777 00000000212 12217370452 024470 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705276 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/JSBeautify.pm000644 €ˆž«€q{Ì00000003073 12217370452 023455 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::JSBeautify; { $Code::TidyAll::Plugin::JSBeautify::VERSION = '0.18'; } use Capture::Tiny qw(capture_merged); use Code::TidyAll::Util qw(write_file); use Moo; use Try::Tiny; extends 'Code::TidyAll::Plugin'; sub _build_cmd { 'js-beautify' } sub transform_file { my ( $self, $file ) = @_; try { my $cmd = join( " ", $self->cmd, $self->argv, $file ); my $output = capture_merged { system($cmd) }; write_file( $file, $output ); } catch { die sprintf( "%s exited with error - possibly bad arg list '%s'", $self->cmd, $self->argv ); }; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::JSBeautify - use js-beautify with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [JSBeautify] select = static/**/*.js argv = --indent-size 2 --brace-style expand =head1 DESCRIPTION Runs L, a JavaScript tidier. =head1 INSTALLATION Install L, then run npm install js-beautify -g Do not confuse this with the C package (without the dash). =head1 CONFIGURATION =over =item argv Arguments to pass to js-beautify =item cmd Full path to js-beautify =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/JSHint.pm000644 777777 777777 00000000212 12217370452 023622 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705277 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/JSHint.pm000644 €ˆž«€q{Ì00000005151 12217370452 022606 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::JSHint; { $Code::TidyAll::Plugin::JSHint::VERSION = '0.18'; } use Code::TidyAll::Util qw(tempdir_simple write_file); use Capture::Tiny qw(capture_merged); use Moo; extends 'Code::TidyAll::Plugin'; sub validate_params { my ( $self, $params ) = @_; delete( $params->{options} ); return $self->SUPER::validate_params($params); } sub _build_cmd { 'jshint' } sub BUILDARGS { my ( $class, %params ) = @_; if ( my $options_string = $params{options} ) { my @options = split( /\s+/, $options_string ); my $conf_dir = tempdir_simple(); my $conf_file = "$conf_dir/jshint.json"; write_file( $conf_file, '{ ' . join( ",\n", map { "\"$_\": true" } @options ) . ' }' ); $params{argv} ||= ""; $params{argv} .= " --config $conf_file"; } return \%params; } sub validate_file { my ( $self, $file ) = @_; my $cmd = sprintf( "%s %s %s", $self->cmd, $self->argv, $file ); my $output = capture_merged { system($cmd) }; if ( $output =~ /\S/ ) { $output =~ s/^$file:\s*//gm; die "$output\n"; } } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::JSHint - use jshint with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: ; With default settings ; [JSHint] select = static/**/*.js ; Specify options inline ; [JSHint] select = static/**/*.js options = bitwise camelcase latedef ; or refer to a jshint.json config file in the same directory ; [JSHint] select = static/**/*.js argv = --config $ROOT/jshint.json where jshint.json looks like { "bitwise": true, "camelcase": true, "latedef": true } =head1 DESCRIPTION Runs L, a JavaScript validator, and dies if any problems were found. =head1 INSTALLATION See installation options at L. One easy method is to install L, then run npm install jshint -g =head1 CONFIGURATION =over =item argv Arguments to pass to jshint =item cmd Full path to jshint =item options A whitespace separated string of options, as documented L. These will be written to a temporary config file and passed as --config to argv. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/JSLint.pm000644 777777 777777 00000000212 12217370452 023626 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705278 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/JSLint.pm000644 €ˆž«€q{Ì00000002426 12217370452 022614 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::JSLint; { $Code::TidyAll::Plugin::JSLint::VERSION = '0.18'; } use Capture::Tiny qw(capture_merged); use Moo; extends 'Code::TidyAll::Plugin'; sub _build_cmd { 'jslint' } sub validate_file { my ( $self, $file ) = @_; my $cmd = sprintf( "%s %s %s", $self->cmd, $self->argv, $file ); my $output = capture_merged { system($cmd) }; die "$output\n" if $output !~ /is OK\./; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::JSLint - use jslint with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [JSLint] select = static/**/*.js argv = --white --vars --regex =head1 DESCRIPTION Runs L, a JavaScript validator, and dies if any problems were found. =head1 INSTALLATION Install L, then run npm install jslint =head1 CONFIGURATION =over =item argv Arguments to pass to jslint =item cmd Full path to jslint =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/MasonTidy.pm000644 777777 777777 00000000212 12217370452 024372 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705279 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/MasonTidy.pm000644 €ˆž«€q{Ì00000002540 12217370452 023355 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::MasonTidy; { $Code::TidyAll::Plugin::MasonTidy::VERSION = '0.18'; } use Mason::Tidy; use Mason::Tidy::App; use Moo; use Text::ParseWords qw(shellwords); extends 'Code::TidyAll::Plugin'; sub _build_cmd { 'masontidy' } sub transform_source { my ( $self, $source ) = @_; local @ARGV = shellwords( $self->argv ); local $ENV{MASONTIDY_OPT}; my $dest = Mason::Tidy::App->run($source); return $dest; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::MasonTidy - use masontidy with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [MasonTidy] select = comps/**/*.{mc,mi} argv = --indent-perl-block 0 --perltidy-argv "-noll -l=78" =head1 DESCRIPTION Runs L, a tidier for L and L components. =head1 INSTALLATION Install L from CPAN. cpanm masontidy =head1 CONFIGURATION =over =item argv Arguments to pass to masontidy =item cmd Full path to masontidy =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/PerlCritic.pm000644 777777 777777 00000000212 12217370452 024523 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705280 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PerlCritic.pm000644 €ˆž«€q{Ì00000002655 12217370452 023515 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::PerlCritic; { $Code::TidyAll::Plugin::PerlCritic::VERSION = '0.18'; } use Capture::Tiny qw(capture_merged); use Moo; extends 'Code::TidyAll::Plugin'; sub _build_cmd { 'perlcritic' } sub validate_file { my ( $self, $file ) = @_; my $cmd = sprintf( "%s %s %s", $self->cmd, $self->argv, $file ); my $output = capture_merged { system($cmd) }; die "$output\n" if $output !~ /^.* source OK\n/; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::PerlCritic - use perlcritic with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: ; Configure in-line ; [PerlCritic] select = lib/**/*.pm argv = --severity 5 --exclude=nowarnings ; or refer to a .perlcriticrc in the same directory ; [PerlCritic] select = lib/**/*.pm argv = --profile $ROOT/.perlcriticrc =head1 DESCRIPTION Runs L, a Perl validator, and dies if any problems were found. =head1 INSTALLATION Install perlcritic from CPAN. cpanm perlcritic =head1 CONFIGURATION =over =item argv Arguments to pass to perlcritic =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/PerlTidy.pm000644 777777 777777 00000000212 12217370452 024217 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705281 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PerlTidy.pm000644 €ˆž«€q{Ì00000003426 12217370452 023206 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::PerlTidy; { $Code::TidyAll::Plugin::PerlTidy::VERSION = '0.18'; } use Capture::Tiny qw(capture_merged); use Perl::Tidy; use Moo; extends 'Code::TidyAll::Plugin'; sub transform_source { my ( $self, $source ) = @_; # perltidy reports errors in two different ways. # Argument/profile errors are output and an error_flag is returned. # Syntax errors are sent to errorfile. # my ( $output, $error_flag, $errorfile, $destination ); $output = capture_merged { $error_flag = Perl::Tidy::perltidy( argv => $self->argv, source => \$source, destination => \$destination, errorfile => \$errorfile ); }; die $errorfile if $errorfile; die $output if $error_flag; print STDERR $output if defined($output); return $destination; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::PerlTidy - use perltidy with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS # In configuration: ; Configure in-line ; [PerlTidy] select = lib/**/*.pm argv = --noll ; or refer to a .perltidyrc in the same directory ; [PerlTidy] select = lib/**/*.pm argv = --profile=$ROOT/.perltidyrc =head1 DESCRIPTION Runs L, a Perl tidier. =head1 INSTALLATION Install perltidy from CPAN. cpanm perltidy =head1 CONFIGURATION =over =item argv Arguments to pass to perltidy =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/PHPCodeSniffer.pm000644 777777 777777 00000000212 12217370452 025222 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705282 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PHPCodeSniffer.pm000644 €ˆž«€q{Ì00000003124 12217370452 024204 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::PHPCodeSniffer; { $Code::TidyAll::Plugin::PHPCodeSniffer::VERSION = '0.18'; } use IPC::System::Simple qw(runx EXIT_ANY); use Capture::Tiny qw(capture_merged); use Moo; extends 'Code::TidyAll::Plugin'; sub _build_cmd { 'phpcs' } sub validate_file { my ( $self, $file ) = @_; my $exit; my @cmd = ( $self->cmd, $self->argv, $file ); my $output = capture_merged { $exit = runx( EXIT_ANY, @cmd ) }; if ( $exit > 0 ) { $output ||= "problem running " . $self->cmd; die "$output\n"; } } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::PHPCodeSniffer - use phpcs with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [PHPCodeSniffer] select = htdocs/**/*.{php,js,css} cmd = /usr/local/pear/bin/phpcs argv = --severity 4 =head1 DESCRIPTION Runs L which analyzes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards. =head1 VERSION version 0.15 =head1 INSTALLATION Install L, then install C from PEAR: pear install PHP_CodeSniffer =head1 CONFIGURATION =over =item argv Arguments to pass to C =item cmd Full path to C =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/PodChecker.pm000644 777777 777777 00000000212 12217370452 024472 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705283 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PodChecker.pm000644 €ˆž«€q{Ì00000003174 12217370452 023461 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::PodChecker; { $Code::TidyAll::Plugin::PodChecker::VERSION = '0.18'; } use Capture::Tiny qw(capture_merged); use Pod::Checker; use Moo; extends 'Code::TidyAll::Plugin'; has 'warnings' => ( is => 'ro' ); sub validate_file { my ( $self, $file ) = @_; my $result; my %options = ( defined( $self->warnings ) ? ( '-warnings' => $self->warnings ) : () ); my $checker = new Pod::Checker(%options); my $output = capture_merged { $checker->parse_from_file( $file, \*STDERR ) }; die $output if $checker->num_errors or ( $self->warnings && $checker->num_warnings ); } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::PodChecker - use podchecker with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: ; Check for errors, but ignore warnings ; [PodChecker] select = lib/**/*.{pm,pod} ; Die on level 1 warnings (can also be set to 2) ; [PodChecker] select = lib/**/*.{pm,pod} warnings = 1 =head1 DESCRIPTION Runs L, a POD validator, and dies if any problems were found. =head1 INSTALLATION Install podchecker from CPAN. cpanm podchecker =head1 CONFIGURATION =over =item warnings Level of warnings to consider as errors - 1 or 2. By default, warnings will be ignored. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/PodSpell.pm000644 777777 777777 00000000212 12217370452 024205 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705284 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PodSpell.pm000644 €ˆž«€q{Ì00000005741 12217370452 023176 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::PodSpell; { $Code::TidyAll::Plugin::PodSpell::VERSION = '0.18'; } use Code::TidyAll::Util qw(basename uniq); use Capture::Tiny qw(); use IPC::System::Simple qw(); use IPC::Run3; use Pod::Spell; use Moo; use Text::ParseWords qw(shellwords); extends 'Code::TidyAll::Plugin'; has 'ispell_argv' => ( is => 'ro', default => sub { '' } ); has 'ispell_cmd' => ( is => 'ro', default => sub { 'ispell' } ); has 'suggest' => ( is => 'ro' ); sub validate_file { my ( $self, $file ) = @_; my ( $text, $error ) = Capture::Tiny::capture { Pod::Spell->new->parse_from_file($file) }; die $error if $error; my ($output); my @cmd = ( $self->ispell_cmd, shellwords( $self->ispell_argv ), "-a" ); eval { run3( \@cmd, \$text, \$output, \$error ) }; $error = $@ if $@; die "error running '" . join( " ", @cmd ) . "': " . $error if $error; my ( @errors, %seen ); foreach my $line ( split( "\n", $output ) ) { if ( my ( $original, $remaining ) = ( $line =~ /^[\&\?\#] (\S+)\s+(.*)/ ) ) { if ( !$seen{$original}++ ) { my ($suggestions) = ( $remaining =~ /: (.*)/ ); if ( $suggestions && $self->suggest ) { push( @errors, sprintf( "%s (suggestions: %s)", $original, $suggestions ) ); } else { push( @errors, $original ); } } } } die sprintf( "unrecognized words:\n%s\n", join( "\n", sort @errors ) ) if @errors; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::PodSpell - use Pod::Spell + ispell with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [PodSpell] select = lib/**/*.{pm,pod} ispell_argv = -p $ROOT/.ispell_english suggest = 1 =head1 DESCRIPTION Uses L in combination with L to spell-check POD. Any seemingly misspelled words will be output one per line. You can specify additional valid words by: =over =item * Adding them to your personal ispell dictionary, e.g. ~/.ispell_english =item * Adding them to an ispell dictionary in the project root, then including this in the configuration: ispell_argv = -p $ROOT/.ispell_english =back The dictionary file should contain one word per line. =head1 INSTALLATION Install ispell from your package manager or from the link above. =head1 CONFIGURATION =over =item ispell_argv Arguments to pass to ispell. "-a" will always be passed, in order to parse the results. =item ispell_cmd Full path to ispell =item suggest If true, show suggestions next to misspelled words. Default is false. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/PodTidy.pm000644 777777 777777 00000000212 12217370452 024037 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705285 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PodTidy.pm000644 €ˆž«€q{Ì00000002611 12217370452 023021 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::PodTidy; { $Code::TidyAll::Plugin::PodTidy::VERSION = '0.18'; } use Capture::Tiny qw(capture_merged); use Pod::Tidy; use Moo; extends 'Code::TidyAll::Plugin'; has 'columns' => ( is => 'ro' ); sub transform_file { my ( $self, $file ) = @_; my $output = capture_merged { Pod::Tidy::tidy_files( files => [$file], inplace => 1, nobackup => 1, verbose => 1, ( $self->columns ? ( columns => $self->columns ) : () ), ); }; die $output if $output =~ /\S/ && $output !~ /does not contain Pod/; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::PodTidy - use podtidy with tidyall =head1 VERSION version 0.18 =head1 SYNOPSIS In configuration: [PodTidy] select = lib/**/*.{pm,pod} columns = 90 =head1 DESCRIPTION Runs L, which will tidy the POD in your Perl or POD-only file. =head1 INSTALLATION Install podtidy from CPAN. cpanm podtidy =head1 CONFIGURATION =over =item columns Number of columns per line =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/PaxHeader/SortLines.pm000644 777777 777777 00000000212 12217370452 024405 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705286 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Plugin/SortLines.pm000644 €ˆž«€q{Ì00000001753 12217370452 023375 0ustar00jonswart000000 000000 package Code::TidyAll::Plugin::SortLines; { $Code::TidyAll::Plugin::SortLines::VERSION = '0.18'; } use Moo; extends 'Code::TidyAll::Plugin'; sub transform_source { my ( $self, $source ) = @_; return join( "\n", sort( grep { /\S/ } split( /\n/, $source ) ) ) . "\n"; } 1; __END__ =pod =head1 NAME Code::TidyAll::Plugin::SortLines - sort lines of a file =head1 VERSION version 0.18 =head1 SYNOPSIS # In configuration: [SortLines] select = .ispell* **/.gitignore =head1 DESCRIPTION Sorts the lines of a file; whitespace lines are discarded. Useful for files containing one entry per line, such as C<.svnignore>, C<.gitignore>, and C<.ispell*>. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Git/PaxHeader/Precommit.pm000644 777777 777777 00000000212 12217370452 023707 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705271 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Git/Precommit.pm000644 €ˆž«€q{Ì00000014713 12217370452 022677 0ustar00jonswart000000 000000 package Code::TidyAll::Git::Precommit; { $Code::TidyAll::Git::Precommit::VERSION = '0.18'; } use Capture::Tiny qw(capture_stdout capture_stderr); use Code::TidyAll; use Code::TidyAll::Util qw(dirname mkpath realpath tempdir_simple write_file); use Cwd qw(cwd); use Guard; use Log::Any qw($log); use IPC::System::Simple qw(capturex run); use Moo; use Try::Tiny; # Public has 'conf_name' => ( is => 'ro' ); has 'git_path' => ( is => 'ro', default => sub { 'git' } ); has 'no_stash' => ( is => 'ro' ); has 'reject_on_error' => ( is => 'ro' ); has 'tidyall_class' => ( is => 'ro', default => sub { "Code::TidyAll" } ); has 'tidyall_options' => ( is => 'ro', default => sub { {} } ); sub check { my ( $class, %params ) = @_; my $fail_msg; try { my $self = $class->new(%params); my $tidyall_class = $self->tidyall_class; # Find conf file at git root my $root_dir = capturex( $self->git_path, "rev-parse", "--show-toplevel" ); chomp($root_dir); my @conf_names = $self->conf_name ? ( $self->conf_name ) : Code::TidyAll->default_conf_names; my ($conf_file) = grep { -f } map { join( "/", $root_dir, $_ ) } @conf_names or die sprintf( "could not find conf file %s", join( " or ", @conf_names ) ); # Store the stash, and restore it upon exiting this scope unless ( $self->no_stash ) { run( $self->git_path, "stash", "-q", "--keep-index" ); scope_guard { run( $self->git_path, "stash", "pop", "-q" ) }; } # Gather file paths to be committed my $output = capturex( $self->git_path, "status", "--porcelain" ); my @files = grep { -f } ( $output =~ /^[MA]\s+(.*)/gm ); my $tidyall = $tidyall_class->new_from_conf_file( $conf_file, no_cache => 1, check_only => 1, mode => 'commit', %{ $self->tidyall_options }, ); my @results = $tidyall->process_paths( map { "$root_dir/$_" } @files ); if ( my @error_results = grep { $_->error } @results ) { my $error_count = scalar(@error_results); $fail_msg = sprintf( "%d file%s did not pass tidyall check\n", $error_count, $error_count > 1 ? "s" : "" ); } } catch { my $error = $_; die "Error during pre-commit hook (use --no-verify to skip hook):\n$error"; }; die "$fail_msg\n" if $fail_msg; } 1; __END__ =pod =head1 NAME Code::TidyAll::Git::Precommit - Git pre-commit hook that requires files to be tidyall'd =head1 VERSION version 0.18 =head1 SYNOPSIS In .git/hooks/pre-commit: #!/usr/bin/env perl use strict; use warnings; use Code::TidyAll::Git::Precommit; Code::TidyAll::Git::Precommit->check(); =head1 DESCRIPTION This module implements a L that checks if all files are tidied and valid according to L, and rejects the commit if not. Files/commits are never modified by this hook. See also L, which validates pushes to a shared repo. =head1 METHODS =over =item check (key/value params...) Class method. Check that all files being added or modified in this commit are tidied and valid according to L. If not, then the entire commit is rejected and the reason(s) are output to the client. e.g. % git commit -m "fixups" CHI.pm CHI/Driver.pm 2 files did not pass tidyall check lib/CHI.pm: *** 'PerlTidy': needs tidying lib/CHI/Driver.pm: *** 'PerlCritic': Code before strictures are enabled at /tmp/Code-TidyAll-0e6K/Driver.pm line 2 [TestingAndDebugging::RequireUseStrict] In an emergency the hook can be bypassed by passing --no-verify to commit: % git commit --no-verify ... or you can just move C<.git/hooks/pre-commit> out of the way temporarily. The configuration file (C or C<.tidyallrc>) must be checked into git in the repo root directory i.e. next to the .git directory. The hook will stash any changes not in the index beforehand, and restore them afterwards, via git stash -q --keep-index .... git stash pop -q This means that if the configuration file has uncommitted changes that are not in the index, they will not affect the tidyall run. Passes mode = "commit" by default; see L. Key/value parameters: =over =item conf_name Conf file name to search for instead of the defaults. =item git_path Path to git to use in commands, e.g. '/usr/bin/git' or '/usr/local/bin/git'. By default, just uses 'git', which will search the user's PATH. =item no_stash Don't attempt to stash changes not in the index. This means the hook will process even files that are not going to be committed. =item tidyall_class Subclass to use instead of L =item tidyall_options Hashref of options to pass to the L constructor =back =back =head1 USING AND (NOT) ENFORCING THIS HOOK This hook must be placed manually in each copy of the repo - there is no way to automatically distribute or enforce it. However, you can make things easier on yourself or your developers as follows: =over =item * Create a directory called C at the top of your repo (note no dot prefix). mkdir -p git/hooks =item * Commit your pre-commit script in C containing: #!/usr/bin/env perl use strict; use warnings; use Code::TidyAll::Git::Precommit; Code::TidyAll::Git::Precommit->check(); =item * Add a setup script in C containing #!/bin/bash chmod +x git/hooks/pre-commit cd .git/hooks ln -s ../../git/hooks/pre-commit =item * Run C (or tell your developers to run it) once for each new clone of the repo =back More information on pre-commit hooks and the impossibility of enforcing them L. See also L, which enforces tidyall on pushes to a remote shared repository. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Git/PaxHeader/Prereceive.pm000644 777777 777777 00000000212 12217370452 024041 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705272 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Git/Prereceive.pm000644 €ˆž«€q{Ì00000022722 12217370452 023030 0ustar00jonswart000000 000000 package Code::TidyAll::Git::Prereceive; { $Code::TidyAll::Git::Prereceive::VERSION = '0.18'; } use Code::TidyAll; use Code::TidyAll::Util qw(dirname realpath tempdir_simple read_file write_file); use Capture::Tiny qw(capture); use Digest::SHA1 qw(sha1_hex); use IPC::System::Simple qw(capturex run); use Moo; use Try::Tiny; # Public has 'allow_repeated_push' => ( is => 'ro', default => sub { 3 } ); has 'conf_name' => ( is => 'ro' ); has 'extra_conf_files' => ( is => 'ro', default => sub { [] } ); has 'git_path' => ( is => 'ro', default => sub { 'git' } ); has 'reject_on_error' => ( is => 'ro' ); has 'tidyall_class' => ( is => 'ro', default => sub { "Code::TidyAll" } ); has 'tidyall_options' => ( is => 'ro', default => sub { {} } ); sub check { my ( $class, %params ) = @_; my $fail_msg; try { my $self = $class->new(%params); my $root_dir = realpath(); local $ENV{GIT_DIR} = $root_dir; my $input = do { local $/; }; $fail_msg = $self->check_input($input); } catch { my $error = $_; if ( $params{reject_on_error} ) { die $error; } else { print STDERR "*** Error running pre-receive hook (allowing push to proceed):\n$error"; } }; die "$fail_msg\n" if $fail_msg; } sub check_input { my ( $self, $input ) = @_; my @lines = split( "\n", $input ); my ( @results, $tidyall ); foreach my $line (@lines) { chomp($line); my ( $base, $commit, $ref ) = split( /\s+/, $line ); # Create tidyall using configuration found in first commit # $tidyall ||= $self->create_tidyall($commit); my @files = $self->get_changed_files( $base, $commit ); foreach my $file (@files) { my $contents = $self->get_file_contents( $file, $commit ); if ( $contents =~ /\S/ && $contents =~ /\n/ ) { push( @results, $tidyall->process_source( $contents, $file ) ); } } } my $fail_msg; if ( my @error_results = grep { $_->error } @results ) { unless ( $self->check_repeated_push($input) ) { my $error_count = scalar(@error_results); $fail_msg = sprintf( "%d file%s did not pass tidyall check", $error_count, $error_count > 1 ? "s" : "" ); } } return $fail_msg; } sub create_tidyall { my ( $self, $commit ) = @_; my $temp_dir = tempdir_simple(); my @conf_names = $self->conf_name ? ( $self->conf_name ) : Code::TidyAll->default_conf_names; my ($conf_file) = grep { $self->get_file_contents( $_, $commit ) } @conf_names or die sprintf( "could not find conf file %s", join( " or ", @conf_names ) ); foreach my $rel_file ( $conf_file, @{ $self->extra_conf_files } ) { my $contents = $self->get_file_contents( $rel_file, $commit ) or die sprintf( "could not find file '%s' in repo root", $rel_file ); write_file( "$temp_dir/$rel_file", $contents ); } my $tidyall = $self->tidyall_class->new_from_conf_file( "$temp_dir/" . $conf_file, mode => 'commit', quiet => 1, %{ $self->tidyall_options }, no_cache => 1, no_backups => 1, check_only => 1, ); return $tidyall; } sub get_changed_files { my ( $self, $base, $commit ) = @_; my $output = capturex( $self->git_path, "diff", "--numstat", "--name-only", "$base..$commit" ); my @files = grep { /\S/ } split( "\n", $output ); return @files; } sub get_file_contents { my ( $self, $file, $commit ) = @_; my ( $contents, $error ) = capture { system( $self->git_path, "show", "$commit:$file" ) }; return $contents; } sub check_repeated_push { my ( $self, $input ) = @_; if ( defined( my $allow = $self->allow_repeated_push ) ) { my $cwd = dirname( realpath($0) ); my $last_push_file = "$cwd/.prereceive_lastpush"; if ( -w $cwd || -w $last_push_file ) { my $push_sig = sha1_hex($input); if ( -f $last_push_file ) { my ( $last_push_sig, $count ) = split( /\s+/, read_file($last_push_file) ); if ( $last_push_sig eq $push_sig ) { ++$count; print STDERR "*** Identical push seen $count times\n"; if ( $count >= $allow ) { print STDERR "*** Allowing push to proceed despite errors\n"; unlink($last_push_file); return 1; } write_file( $last_push_file, join( " ", $push_sig, $count ) ); return 0; } } write_file( $last_push_file, join( " ", $push_sig, 1 ) ); } } return 0; } 1; __END__ =pod =head1 NAME Code::TidyAll::Git::Prereceive - Git pre-receive hook that requires files to be tidyall'd =head1 VERSION version 0.18 =head1 SYNOPSIS In .git/hooks/pre-receive: #!/usr/bin/perl use Code::TidyAll::Git::Prereceive; use strict; use warnings; Code::TidyAll::Git::Prereceive->check(); # or my $input = do { local $/; }; # Do other things with $input here my $hook = Code::TidyAll::Git::Prereceive->new(); if (my $error = $hook->check_input($input)) { die $error; } =head1 DESCRIPTION This module implements a L that checks if all pushed files are tidied and valid according to L, and rejects the push if not. This is typically used to validate pushes from multiple developers to a shared repo, possibly on a remote server. See also L, which operates locally. =head1 METHODS =over =item check (key/value params...) An all-in-one class method. Reads commit info from standard input, then checks that all files being added or modified in this push are tidied and valid according to L. If not, then the entire push is rejected and the reason(s) are output to the client. e.g. % git push Counting objects: 9, done. ... remote: [checked] lib/CHI/Util.pm remote: Code before strictures are enabled on line 13 [TestingAndDebugging::RequireUseStrict] remote: remote: 1 file did not pass tidyall check To ... ! [remote rejected] master -> master (pre-receive hook declined) The configuration file (C or C<.tidyallrc>) must be checked into git in the repo root directory, i.e. next to the .git directory. In an emergency the hook can be bypassed by pushing the exact same set of commits 3 consecutive times (configurable via L): % git push ... remote: 1 file did not pass tidyall check % git push ... *** Identical push seen 2 times remote: 1 file did not pass tidyall check % git push ... *** Identical push seen 3 times *** Allowing push to proceed despite errors Or you can disable the hook in the repo being pushed to, e.g. by renaming .git/hooks/pre-receive. If an unexpected runtime error occurs, it is reported but by default the commit will be allowed through (see L). Passes mode = "commit" by default; see L. Key/value parameters: =over =item allow_repeated_push Number of times a push must be repeated exactly after which it will be let through regardless of errors. Defaults to 3. Set to 0 or undef to disable this feature. =item conf_name Conf file name to search for instead of the defaults. =item extra_conf_files A listref of extra configuration files referred to from the main configuration file, e.g. extra_conf_files => ['perlcriticrc', 'perltidyrc'] These files will be pulled out of the repo alongside the main configuration file. If you don't list them here then you'll get errors like 'cannot find perlcriticrc' when the hook runs. =item git_path Path to git to use in commands, e.g. '/usr/bin/git' or '/usr/local/bin/git'. By default, just uses 'git', which will search the user's PATH. =item reject_on_error Whether C should reject the commit when an unexpected runtime error occurs. By default, the error will be reported but the commit will be allowed. =item tidyall_class Subclass to use instead of L =item tidyall_options Hashref of options to pass to the L constructor. You can use this to override the default options mode => 'commit', quiet => 1, or pass additional options. =back =item new (key/value params...) Constructor. Takes the same parameters documented in check(), above, and returns a new object which you can then call L on. =item check_input (input) Run a check on I, the text block of lines that came from standard input. You can call this manually before or after you do other processing on the input. Returns an error string if there was a problem, undef if no problems. =back =head1 KNOWN BUGS This hook will ignore any files with only a single line of content (no newlines), as an imperfect way of filtering out symlinks. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Code-TidyAll-0.18/lib/Code/TidyAll/Git/PaxHeader/Util.pm000644 777777 777777 00000000212 12217370452 022665 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705273 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Git/Util.pm000644 €ˆž«€q{Ì00000001072 12217370452 021647 0ustar00jonswart000000 000000 package Code::TidyAll::Git::Util; { $Code::TidyAll::Git::Util::VERSION = '0.18'; } use Cwd qw(realpath); use Code::TidyAll::Util qw(pushd uniq); use IPC::System::Simple qw(capturex); use strict; use warnings; use base qw(Exporter); our @EXPORT_OK = qw(git_uncommitted_files); sub git_uncommitted_files { my ($dir) = @_; $dir = realpath($dir); my $pushd = pushd($dir); my $output = capturex( "git", "status" ); my @files = ( $output =~ /(?:new file|modified):\s+(.*)/g ); @files = uniq( map { "$dir/$_" } @files ); return @files; } 1; Code-TidyAll-0.18/lib/Code/TidyAll/Config/PaxHeader/INI000775 777777 777777 00000000212 12217370452 022443 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705268 18 SCHILY.nlink=3 Code-TidyAll-0.18/lib/Code/TidyAll/Config/INI/000775 €ˆž«€q{Ì00000000000 12217370452 021477 5ustar00jonswart000000 000000 Code-TidyAll-0.18/lib/Code/TidyAll/Config/INI/PaxHeader/Reader.pm000644 777777 777777 00000000212 12217370452 024253 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705269 18 SCHILY.nlink=1 Code-TidyAll-0.18/lib/Code/TidyAll/Config/INI/Reader.pm000644 €ˆž«€q{Ì00000001061 12217370452 023233 0ustar00jonswart000000 000000 package Code::TidyAll::Config::INI::Reader; { $Code::TidyAll::Config::INI::Reader::VERSION = '0.18'; } use strict; use warnings; use base qw(Config::INI::Reader); sub set_value { my ( $self, $name, $value ) = @_; if ( exists( $self->{data}{ $self->current_section }{$name} ) ) { die "cannot list multiple config values for '$name'" unless $name =~ /select|ignore/; $self->{data}{ $self->current_section }{$name} .= " " . $value; } else { $self->{data}{ $self->current_section }{$name} = $value; } } 1; Code-TidyAll-0.18/etc/PaxHeader/editors000775 777777 777777 00000000212 12217370452 020061 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705256 18 SCHILY.nlink=4 Code-TidyAll-0.18/etc/editors/000775 €ˆž«€q{Ì00000000000 12217370452 017115 5ustar00jonswart000000 000000 Code-TidyAll-0.18/etc/editors/PaxHeader/tidyall.el000644 777777 777777 00000000212 12217370452 022115 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705257 18 SCHILY.nlink=1 Code-TidyAll-0.18/etc/editors/tidyall.el000644 €ˆž«€q{Ì00000010775 12217370452 021111 0ustar00jonswart000000 000000 ;;; tidyall.el -- Apply tidyall (https://metacpan.org/module/tidyall) to the current buffer ;; Copyright (C) 2012 Jonathan Swartz ;; Author: Jonathan Swartz ;; Keywords: extensions ;; Status: Tested with Emacs 24.1.1 ;; This file is *NOT* part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, 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. ;; This package implements a single function, tidyall-buffer, which ;; runs tidyall (https://metacpan.org/module/tidyall) on the current buffer. ;; If successful, the contents of the buffer are replaced with the tidied contents, and ;; the buffer is saved if tidyall-autosave is true. The modifications should be ;; undoable. ;; If tidyall generates any errors, the buffer is not changed, and a separate window ;; called *tidyall-output* is opened displaying the error. ;; To operate on just a region of the buffer, use narrow-to-region. ;; To assign this command to ctrl-t globally: ;; ;; (global-set-key "\C-t" 'tidyall-buffer) ;; ;; Or to assign it locally in, e.g., perl-mode: ;; ;; (setq perl-mode-hook ;; '(lambda () ;; (local-set-key "\C-t" 'tidyall-buffer) ;; )) ;; ;; (This replaces the default binding to transpose-chars, which I never use but ymmv.) ;; The variable `tidyall-cmd` contains the path to the tidyall command. ;; (setq tidyall-cmd "tidyall") ;; The variable `tidyall-autosave` indicates whether to save the buffer after a successful ;; tidy - defaults to t ;; (setq tidyall-autosave t) (defun tidyall-buffer () "Run tidyall on the current buffer." (interactive) (let ((file (buffer-file-name))) (cond ((null file) (message "buffer has no filename")) (t (let* ((command (concat tidyall-cmd " -m editor --pipe " file)) (output-buffer (get-buffer-create "*tidyall-output*")) (error-buffer (get-buffer-create "*tidyall-error*")) (error-file (make-temp-file "tidyall_error")) (start (point-min)) (end (point-max)) (orig-window-start (window-start (selected-window))) (orig-point (point))) (with-current-buffer output-buffer (erase-buffer)) (with-current-buffer error-buffer (erase-buffer)) (let* ((result (call-process-region start end shell-file-name nil (list output-buffer error-file) nil shell-command-switch command)) (output (with-current-buffer output-buffer (buffer-string)))) (kill-buffer output-buffer) (cond ((zerop result) ;; Success. Replace content if it changed ;; (cond ((not (equal output (buffer-string))) (delete-region start end) (insert output) ;; Restore original window start and point as much as ;; possible. Go to beginning of line since we'll probably be ;; at a random point around our original line after the tidy. ;; (set-window-start (selected-window) orig-window-start) (goto-char orig-point) (beginning-of-line) (message (concat "tidied " file))) (t (message (concat "checked " file)))) (when tidyall-autosave (save-buffer)) (delete-windows-on error-buffer) (kill-buffer error-buffer)) (t ;; Error. Display in other window ;; (with-current-buffer error-buffer (insert-file-contents error-file)) (when (< (length (window-list)) 2) (split-window-vertically)) (set-window-buffer (next-window) error-buffer))))))))) Code-TidyAll-0.18/etc/editors/PaxHeader/tidyall.vim000644 777777 777777 00000000212 12217370452 022310 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705258 18 SCHILY.nlink=1 Code-TidyAll-0.18/etc/editors/tidyall.vim000644 €ˆž«€q{Ì00000001165 12217370452 021275 0ustar00jonswart000000 000000 " Run tidyall on the current buffer. If an error occurs, show it and leave it " in tidyall.ERR, and undo any changes. command! TidyAll :call TidyAll() function! TidyAll() let cur_pos = getpos( '.' ) let cmdline = ':1,$!tidyall --mode editor --pipe %:p 2> tidyall.ERR' execute( cmdline ) if v:shell_error echo "\nContents of tidyall.ERR:\n\n" . system( 'cat tidyall.ERR' ) silent undo else call system( 'rm tidyall.ERR' ) endif call setpos( '.', cur_pos ) endfunction " Uncomment to set leader to , " let mapleader = ',' " Bind to ,t (or leader+t) map t :TidyAll Code-TidyAll-0.18/bin/PaxHeader/tidyall000755 777777 777777 00000000212 12217370452 020045 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1379791146 20 atime=1379791146 23 SCHILY.dev=16777220 22 SCHILY.ino=5705254 18 SCHILY.nlink=1 Code-TidyAll-0.18/bin/tidyall000755 €ˆž«€q{Ì00000054473 12217370452 017044 0ustar00jonswart000000 000000 #!/usr/bin/perl use Config; use Cwd qw(cwd realpath); use Getopt::Long; use Capture::Tiny qw(capture_merged); use Code::TidyAll; use Code::TidyAll::Util qw(can_load dirname rel2abs); use strict; use warnings; my $usage = ' Usage: tidyall [options] [file] ... See https://metacpan.org/module/tidyall for full documentation. Options: -a, --all Process all files in project -g, --git Process all added/modified files according to git -h, --help Print help message -l, --list List each file along with the plugins it matches -m, --mode Mode (e.g. "editor", "commit") - affects which plugins run -p , --pipe Read from STDIN, output to STDOUT/STDERR -r, --recursive Descend recursively into directories listed on command line -s, --svn Process all added/modified files according to svn -q, --quiet Suppress output except for errors -v, --verbose Show extra output -I I Add one or more paths to @INC --backup-ttl Amount of time before backup files can be purged --check-only Just check each file, don\'t modify --conf-file Relative or absolute path to conf file --conf-name Conf file name to search for --data-dir Contains metadata, defaults to root/.tidyall.d --iterations Number of times to repeat each transform - default is 1 --no-backups Don\'t backup files before processing --no-cache Don\'t cache last processed times --output-suffix Suffix to add to tidied file --refresh-cache Erase any existing cache info before processing each file --root-dir Specify root directory explicitly --tidyall-class Subclass to use instead of Code::TidyAll --version Show version '; sub version { my $version = $Code::TidyAll::VERSION || 'unknown'; print "tidyall $version on perl $] built for $Config{archname}\n"; exit; } sub usage { print $usage; exit; } my ( %params, $all_files, $conf_file, $conf_name, $git_files, $help, $inc_dirs, $pipe, $svn_files, $version ); my @conf_names = Code::TidyAll->default_conf_names; GetOptions( 'backup-ttl=i' => \$params{backup_ttl}, 'check-only' => \$params{check_only}, 'conf-file=s' => \$conf_file, 'conf-name=s' => \$conf_name, 'data-dir=s' => \$params{data_dir}, 'no-backups' => \$params{no_backups}, 'no-cache' => \$params{no_cache}, 'output-suffix=s' => \$params{output_suffix}, 'refresh-cache' => \$params{refresh_cache}, 'root-dir=s' => \$params{root_dir}, 'tidyall-class=s' => \$params{tidyall_class}, 'version' => \$version, 'a|all' => \$all_files, 'g|git' => \$git_files, 'h|help' => \$help, 'l|list' => \$params{list_only}, 'm|mode=s' => \$params{mode}, 'p|pipe=s' => \$pipe, 'r|recursive' => \$params{recursive}, 's|svn' => \$svn_files, 'q|quiet' => \$params{quiet}, 'v|verbose' => \$params{verbose}, 'I' => \$inc_dirs, ) or usage(); version() if $version; usage() if $help; @conf_names = ($conf_name) if defined($conf_name); unshift( @INC, split( /\s*,\s*/, $inc_dirs ) ) if defined($inc_dirs); %params = map { ( $_, $params{$_} ) } grep { defined( $params{$_} ) } keys(%params); ($conf_file) = ( grep { -f } map { "$params{root_dir}/$_" } @conf_names ) if $params{root_dir} && !$conf_file; my $tidyall_class = $params{tidyall_class} || 'Code::TidyAll'; my ( $ct, @paths ); if ($pipe) { my $status = handle_pipe($pipe); exit($status); } elsif ( ( $all_files || $svn_files || $git_files ) ) { die "cannot use filename(s) with -a/--all, -s/--svn, or -g/--git" if @ARGV; $conf_file ||= $tidyall_class->find_conf_file( \@conf_names, cwd() ); $ct = $tidyall_class->new_from_conf_file( $conf_file, %params ); if ($all_files) { @paths = $ct->find_matched_files; } elsif ($svn_files) { require Code::TidyAll::SVN::Util; @paths = Code::TidyAll::SVN::Util::svn_uncommitted_files( $ct->root_dir ); } elsif ($git_files) { require Code::TidyAll::Git::Util; @paths = Code::TidyAll::Git::Util::git_uncommitted_files( $ct->root_dir ); } } elsif ( @paths = @ARGV ) { $conf_file ||= $tidyall_class->find_conf_file( \@conf_names, dirname( $paths[0] ) ); $ct = $tidyall_class->new_from_conf_file( $conf_file, %params ); } else { print "must pass -a/--all, -s/--svn, -g/--git, -p/--pipe, or filename(s)\n"; usage(); } my @results = $ct->process_paths(@paths); my $status = ( grep { $_->error } @results ) ? 1 : 0; exit($status); sub handle_pipe { my ($pipe_filename) = @_; $params{$_} = 1 for ( 'no_backups', 'no_cache', 'quiet' ); $params{$_} = 0 for ('verbose'); $conf_file ||= $tidyall_class->find_conf_file( \@conf_names, dirname($pipe_filename) ); my $ct = $tidyall_class->new_from_conf_file( $conf_file, %params ); my $root_dir = $ct->root_dir; my $source = do { local $/; }; # Merge stdout and stderr and output all to stderr, so that stdout is # dedicated to the tidied content # my $result; my $output = capture_merged { $result = $ct->process_source( $source, $ct->_small_path( rel2abs($pipe_filename) ) ); }; print STDERR $output; if ( my $error = $result->error ) { print $source; # Error already printed above return 1; } elsif ( $result->state eq 'no_match' ) { print $source; print STDERR "No plugins apply for '$pipe' in config"; return 1; } elsif ( $result->state eq 'checked' ) { print $source; return 0; } else { print $result->new_contents; return 0; } } 1; __END__ =pod =head1 NAME tidyall - Your all-in-one code tidier and validator =head1 VERSION version 0.18 =head1 SYNOPSIS # Create a tidyall.ini or .tidyallrc at the top of your project # [PerlTidy] select = **/*.{pl,pm,t} argv = -noll -it=2 [PerlCritic] select = lib/**/*.pm ignore = lib/UtterHack.pm argv = -severity 3 # Process all files in the current project, # look upwards from cwd for conf file # % tidyall -a # Process one or more specific files, # look upwards from the first file for conf file # % tidyall file [file...] # Process a directory recursively # % tidyall -r dir =head1 DESCRIPTION There are a lot of great code tidiers and validators out there. C makes them available from a single unified interface. You can run C on a single file or on an entire project hierarchy, and configure which tidiers/validators are applied to which files. C will back up files beforehand, and for efficiency will only consider files that have changed since they were last processed. =head2 What's a tidier? What's a validator? A I transforms a file so as to improve its appearance without changing its semantics. Examples include L, L and L. A I analyzes a file for some definition of correctness. Examples include L, L and L. Many tidiers are also validators, e.g. C will throw an error on badly formed Perl. To use a tidier or validator with C it must have a corresponding plugin class, usually under the prefix C. This distribution comes with plugins for: =over =item * Perl: L, L =item * Pod: L, L, L =item * Mason: L =item * JavaScript: L, L, L =item * CSS: L =item * PHP: L =item * Misc: L =back See L for information about creating your own plugin. =head1 USING TIDYALL C works on a project basis, where a project is just a directory hierarchy of files. svn or git working directories are typical examples of projects. The top of the project is called the I. In the root directory you'll need a config file named C or C<.tidyallrc>; it defines how various tidiers and validators will be applied to the files in your project. C will find your root directory and config file automatically depending on how you call it: =over =item C<< tidyall file [file...] >> C will search upwards from the first file for the conf file. =item C<< tidyall -p/--pipe file >> C will search upwards from the specified file for the conf file. =item C<< tidyall -a/--all >> or C<< tidyall -s/--svn >> or C<< tidyall -g/--git >> C will search upwards from the current working directory for the conf file. =item C<< tidyall -a --root-dir dir >> C will expect to find the conf file in the specified root directory. =back You can also pass --conf-name to change the name that is searched for, or --conf-file to specify an explicit path. =head1 CONFIGURATION The config file (C or C<.tidyallrc>) is in L format. Here's a sample: [PerlTidy] select = **/*.{pl,pm,t} argv = -noll -it=2 [PerlCritic] select = lib/**/*.pm ignore = lib/UtterHack.pm lib/OneTime/*.pm argv = -severity 3 [PodTidy] select = lib/**/*.{pm,pod} In order, the three sections declare: =over =item * Apply C with settings "-noll -it=2" to all *.pl, *.pm, and *.t files. =item * Apply C with severity 3 to all Perl modules somewhere underneath "lib/", except for "lib/UtterHack.pm". =item * Apply C with default settings to all *.pm and *.pod files underneath "lib/". =back =head2 Standard configuration elements =over =item [class] or [class description] The header of each section refers to a tidyall I. The name is automatically prefixed with C unless it begins with a '+', e.g. ; Uses plugin Code::TidyAll::Plugin::PerlTidy ; [PerlTidy] ; Uses plugin My::TidyAll::Plugin ; [+My::TidyAll::Plugin] You can also include an optional description after the class. The description will be ignored and only the first word will be used for the plugin. This allows you to a list a plugin more than once, with different configuration each time. For example, two different C configurations: ; Be brutal on libraries ; [PerlCritic strict] select = lib/**/*.pm argv = --brutal ; but gentle on scripts ; [PerlCritic lenient] select = bin/**/*.pl argv = --gentle Warning: If you simply list the same plugin twice with no description (or the same description), one of them will be silently ignored. =item select One or more L patterns, separated by whitespace or on multiple lines, indicating which files to select. At least one is required. e.g. ; All .t and .pl somewhere under bin and t; ; plus all .pm files directly under lib/Foo and lib/Bar ; select = {bin,t}/**/*.p[lm] select = lib/{Foo,Bar}/*.pm ; All .txt files anywhere in the project ; select = **/*.txt The pattern is relative to the root directory and should have no leading slash. All standard glob characters (C<*>, C, C<[]>, C<{}>) will work; in addition, C<**> can be used to represent zero or more directories. See L documentation for more details. =item ignore One or more L patterns, separated by whitespace or on multiple lines, indicating which files to ignore. This is optional and overrides C