The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Dependencies::Searcher - Search for modules used 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 retrieve this list. It can also be handy sometimes to check if your Makefile.PL contains all the prerequisite that are needed for your distribution.

This module's aim is to keep track of the list of modules your distribution need, under the form of a cpanfile.

Dependencies::Searcher will check for any requires or use in your module repository, and report it into a 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 cases, see dissociate() documentation).

This project has begun because I was sometimes forgetting to keep track of my dependencies, and I just wanted to run a simple script that updated the list in a convenient way.

Not a dependencies-tree tool

Dependencies::Searcher only finds direct dependencies, not dependencies of dependencies, it scans recursively directories of your module to find declared dependencies.

Once you generated a cpanfile with Dependencies::Searcher, it's possible to pass this list 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, the search() subroutine will be used to retrieve modules names into lines containing patterns and return them into an array (containing also some dirt).

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.

avoid_superfluous(@modules)

Move dependencies lines from an array to an another unless it is considered as a "superfluous" unneccessary case : minimal Perl versions, use autodie, use warnings. These stuff has to be removed, not cleaned. 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.

coucou($tring, $color)

Stupid DIY logger

CAVEATS

Some are able to do it using a one-liner (fun))

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

Though, it don't really work, that's why I made this module.

SOURCE CODE

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

BUGS, ISSUES, TODOs

The simpliest way report any bugs or feature requests is to use Gitlab:

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

If your prefer, you can use the very perlish way and send a mail to bug-dependencies-searcher at rt.cpan.org, or using 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.

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 riseup.net>

CONTRIBUTORS

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

  • Alexandr Ciornii (chorny) advises on version numbers

ACKNOWLEDGEMENTS

Module::Extract::Use

Was the main inspiration for this one. Not recursive though...

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

See also :

  • https://metacpan.org/module/Module::ScanDeps

  • 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.