NAME

Dependencies::Searcher - Search for modules used or required by a distribution.

SYNOPSIS

use Dependencies::Searcher;

my $searcher = Dependencies::Searcher->new();
my @elements = $searcher->get_files();
my @uses = $searcher->get_modules($path, "use");
my @uniq_modules = $searcher->uniq(@uses);

$searcher->dissociate(@uniq_modules);

$searcher->generate_report($searcher->non_core_modules);

# Prints to cpanfile
# requires 'Data::Printer', '0.35';
# requires Moose, '2.0602';
# requires IPC::Cmd;
# requires Module::Version;
# ...

Synopsis from Dependencies::Searcher::AckRequester

# Places to search...
my @path = ("./lib", "./Makefile.PL", "./script");

# Params for Ack
my @params = ('--perl', '-hi', $pattern, @path);

# Absolute path to the Ack binary
my $ack_path = $requester->get_path();

# Build the command for IPC::Cmd
my $cmd_use = $requester->build_cmd(@params);

# Execute the command and retrieve the output
my @moduls = $requester->search($cmd_use);

DESCRIPTION

Maybe you don't want to have to list all the dependencies of your Perl application by hand and want an automated way to build it. Maybe you forgot to do it for a long time ago. Or just during a short period. Anyway, you've add lots of CPAN modules. Carton is here to help you manage dependencies between your development environment and production, but how to keep track of the list of modules you will pass to Carton?

Event if it is a no brainer to keep track of this list by adding it by hand, it can be much better not to have to do it.

You will need a tool that will check for any requires or use in your module package, and report it into a file that could be used as an input Carton cpanfile. Any duplicated entry will be removed and modules versions will be checked and made available. Core modules will be ommited because you don't need to install them (except in some special case, see dissociate() documentation).

This project has begun because it has happened to me, and I don't want to search for modules to install by hand, I just want to run a simple script that update the list in a convenient way. It was much more longer to write the module than to search by hand so I wish it could be useful for you now.

This module is made to search dependencies for installed distributions, it is not supposed to manage anything else.

WHY ISN'T IT JUST ANOTHER MODULE::SCANDEPS ?

Module::ScanDeps is a bi-dimentional recursive scanner: it features dependencies and directories recursivity.

Dependencies::Searcher only found direct dependencies, not dependencies of dependencies, it scans recursively directories but not dependencies..

These direct dependencies are passed to the Perl toolchain (cpanminus) that will take care of any recursive dependencies.

SUBROUTINES/METHODS

get_files()

get_files() returns an array containing which file or directories has been found in the current root distribution directory. We suppose it can find dependancies in 3 different places :

  • files in lib/ directory, recursively

  • Makefile.PL

  • script/ directory, i.e. if we use a Catalyst application

  • maybe it should look in t/ directory (todo)

If the lib/ directory don't exist, the program die because we consider we are not into a plain old Perl Module.

This is work in progress, if you know other places where we can find stuff, please report a bug.

get_modules("pattern", @elements)

You must pass a pattern to search for, and the elements (files or directories) where you want to search (array of strings from get_files()).

These patterns should be ^use or ^require.

Then, Ack will be used to retrieve modules names into lines containing patterns and return them into an array (containing also some dirt). See Dependencies::Searcher::AckRequester for more informations.

merge_dependencies(@modules, @modules)

Simple helper method that will merge use and require arrays if you search for both. Return an uniq array. It got a little caveat, see CAVEATS.

make_it_real(@modules)

Move dependencies lines from an array to an another unless it is considered as a special case : minimal Perl versions, use autodie, use warnings. These stuff has to be removed. Return a real modules array (real interresting modules).

clean_everything(@modules)

After removing irrelevant stuff, we need to clean what is leaving and is considered as being crap (not strictly <CName::Of::Module>) but needs some cleaning. We are going to remove everything but the module name (even version numbers).

This code section is well commented (because it is regex-based) so, please refer to it directly.

It returns an array of clean modules.

uniq(@modules)

Make each array element uniq, because one dependency can be found many times. Return an array of unique modules.

dissociate(@modules)

Dissociate core / non-core modules using the awesome Module::Corelist::is_core method, that search in the current Perl version if the module is from Perl core or not. Note that results can be different according to the environment.

More, you can have two versions of the same module installed on your environment (even if you use local::lib when you install a recent version of a file that has been integrated into Perl core (this version hasn't necessary been merged into core).

So dissociate() checks both and compares it, to be sure that the found core module is the "integrated" version, not a fresh one that you have installed yourself. If it is fresh, the module is considered as a non-core.

This method don't return anything, but it stores found dependencies on the two core_modules and non_core_modules Moose attributes arrays.

generate_report()

Generate the cpanfile for Carton, based on data contained into core_modules and non_core_modules attributes, with optionnal version number (if version number can't be found, dependency name is print alone).

Generate a hash containing the modules could be achieved. Someday.

get_path()

Returns the ack full path if installed. Set the full_path Moose attribute that will be used by ICP::Cmd. It verify also that Ack is reachable or warns about it.

build_cmd(@params)

build_cmd() takes as parameter all the arguments Ack will need. Dependencies::Searcher defines it like this :

  • --perl : tells to search in Perl like files (*.pm, *.pl, etc.)

  • -hi : suppress the prefixing filename on output + ignore case

  • $pattern : must be passed from your implementation

  • @path : files and directories where ack will go

    All these params are merged in an only array reference that is returned for later use with IPC::Cmd.

ack($params_array_ref)

Execute the IPC::Cmd command that calls ack and returns an array of potentially interesting lines, containing dependencies names but some crap inside too.

rm_comments($line_that_should_be_cleaned_of_any_comment)

Supposed to remove any comment from a line.

CAVEATS

Low Win32 / Cygwin support

This module was'nt supposed to run under Win32 / Cygwin environments because it was using non portable code with slashes. I hope this gets better since it has been rewritten using Path::Class but it still need some testing.

It also us-e Ack as a hack through a system command even if it was not supposed to be used like that. Yes, this is dirty. Yes, I plan to change things, even if Ack do the stuff proudly this way.

Thanks to cpantesters.org community reports, things should go better and better.

Fun : some are able to do it using a one-liner

Command Line Magic (@climagic) tweeted 4:17 PM on lun., nov. 25, 2013

# Not perfect, but gives you a start on the Perl modules in use.
grep -rh ^use --include="*.pl" --include="*.pm" . | sort | uniq -c

See original Tweet https://twitter.com/climagic/status/404992356513902592

BUGS

Please report any bugs or feature requests to bug-dependencies-searcher at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Dependencies-Searcher. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

REPOSITORY

https://git.framasoft.org/smonff/dependencies-searcher

TODOs

Most of the time, todos and features are on Github and Questub. See https://github.com/smonff/dependencies-searcher/issues

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Dependencies::Searcher

You can also look for information at:

See https://github.com/smonff/dependencies-searcher/

AUTHOR

smonff, <smonff at gmail.com>

CONTRIBUTORS

  • Nikolay Mishin (mishin) helps to make it more cross-platform

  • Alexandr Ciornii (chorny) advises on version numbers

ACKNOWLEDGEMENTS

Module::Extract::Use

Was the main inspiration for this one. First, I want to use it for my needs but it was not recursive...

See https://metacpan.org/module/Module::Extract::Use

Module::CoreList

What modules shipped with versions of perl. I use it extensively to detect if the module is from Perl Core or not.

See http://perldoc.perl.org/Module/CoreList.html

http://beyondgrep.com/|Ack

Ack gives me the wish to try to write this module. It was pure Perl so I've choose it because it was possible to install it through CPAN during the distribution installation process. Even if Ack was not meant for being used programatically, this hacked use of Ack did the job during the first part of this module's life. These dready parts (use of Ack with IPC::Cmd) have been removed since.

See also :

  • https://metacpan.org/module/Perl::PrereqScanner

  • http://stackoverflow.com/questions/17771725/

  • https://metacpan.org/module/Dist::Zilla::Plugin::AutoPrereqs

LICENSE AND COPYRIGHT

Copyright 2013-2016 Sebastien Feugere.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.