Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kentnl/path-isdev
Determine if a given Path resembles a development source tree
https://github.com/kentnl/path-isdev
Last synced: 4 days ago
JSON representation
Determine if a given Path resembles a development source tree
- Host: GitHub
- URL: https://github.com/kentnl/path-isdev
- Owner: kentnl
- License: other
- Created: 2013-07-06T12:45:36.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2017-03-09T20:40:55.000Z (over 7 years ago)
- Last Synced: 2024-06-19T02:05:03.841Z (5 months ago)
- Language: Perl
- Size: 1.65 MB
- Stars: 2
- Watchers: 2
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.mkdn
- Changelog: Changes
- License: LICENSE
Awesome Lists containing this project
README
# NAME
Path::IsDev - Determine if a given Path resembles a development source tree
# VERSION
version 1.001004
# SYNOPSIS
use Path::IsDev qw(is_dev);
if( is_dev('/some/path') ) {
...
} else {
...
}# DESCRIPTION
This module is more or less a bunch of heuristics for determining if a given path
is a development tree root of some kind.This has many useful applications, notably ones that require behaviours for "installed"
modules to be different to those that are still "in development"# FUNCTIONS
## debug
Debug callback.
To enable debugging:
export PATH_ISDEV_DEBUG=1
## `is_dev`
Using an `import`'ed `is_dev`:
if( is_dev( $path ) ) {
}
Though the actual heuristics used will be based on how `import` was called.
Additionally, you can call
Path::IsDev::is_dev
without `import`ing anything, and it will behave exactly the same as if you'd imported
it usinguse Path::IsDev qw( is_dev );
That is, no `set` specification is applicable, so you'll only get the "default".
# UNDERSTANDING AND DEBUGGING THIS MODULE
Understanding how this module works, is critical to understand where you can use it, and the consequences of using it.
This module operates on a very simplistic level, and its easy for false-positives to occur.
There are two types of Heuristics, Postive/Confirming Heuristics, and Negative/Disconfirming Heuristics.
Positive Heuristics and Negative Heuristics are based solely on the presence of specific marker files in a directory, or special
marker directories.For instance, the files `META.yml`, `Makefile.PL`, and `Build.PL` are all **Positive Heuristic** markers, because their
presence often indicates a "root" of a development tree.And for instance, the directories `t/`, `xt/` and `.git/` are also **Positive Heuristic** markers, because these structures
are common in `perl` development trees, and uncommon in install trees.However, these markers sometimes go wrong, for instance, consider you have a `local::lib` or `perlbrew` install in `$HOME`
$HOME/
$HOME/lib/
$HOME/perl5/perls/perl-5.19.3/lib/site_perl/Etc.
Under normal circumstances, neither `$HOME` nor those 3 paths are considered `dev`.
However, all it takes to cause a false positive, is for somebody to install a `t` or `xt` directory, or a marker file in one of
the above directories for `path_isdev($dir)` to return true.This may not be a problem, at least, until you use `Path::FindDev` which combines `Path::IsDev` with recursive up-level
traversal.$HOME/
$HOME/lib/
$HOME/perl5/perls/perl-5.19.3/lib/site_perl/find_dev('$HOME/perl5/perls/perl-5.19.3/lib/site_perl/') # returns false, because it is not inside a dev directory
mkdir $HOME/t
find_dev('$HOME/perl5/perls/perl-5.19.3/lib/site_perl/') # returns $HOME, because $HOME/t exists.
And it is this kind of problem that usually catches people off guard.
PATH_ISDEV_DEBUG=1 \
perl -Ilib -MPath::FindDev=find_dev \
-E "say find_dev(q{/home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl})"...
[Path::IsDev=0] + ::Tool::Dzil => 0 : dist.ini does not exist
[Path::IsDev=0] + ::Tool::MakeMaker => 0 : Makefile.PL does not exist
[Path::IsDev=0] + ::Tool::ModuleBuild => 0 : Build.PL does not exist
[Path::IsDev=0] + ::META => 0 : META.json does not exist
[Path::IsDev=0] + ::META => 1 : META.yml exists
[Path::IsDev=0] + ::META => 1 : /home/kent/perl5/META.yml is a file
[Path::IsDev=0] + ::META matched path /home/kent/perl5
/home/kent/perl5Whoops!.
[Path::IsDev=0] + ::META => 1 : META.yml exists
[Path::IsDev=0] + ::META => 1 : /home/kent/perl5/META.yml is a fileNo wonder!
rm /home/kent/perl5/META.yml
PATH_ISDEV_DEBUG=1 \
perl -Ilib -MPath::FindDev=find_dev \
-E "say find_dev(q{/home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl})"...
[Path::IsDev=0] Matching /home/kent/perl5
...
[Path::IsDev=0] + ::TestDir => 0 : xt does not exist
[Path::IsDev=0] + ::TestDir => 1 : t exists
[Path::IsDev=0] + ::TestDir => 1 : /home/kent/perl5/t is a dir
[Path::IsDev=0] + ::TestDir matched path /home/kent/perl5
/home/kent/perl5Double whoops!
[Path::IsDev=0] + ::TestDir => 1 : t exists
[Path::IsDev=0] + ::TestDir => 1 : /home/kent/perl5/t is a dirAnd you could keep doing that until you rule out all the bad heuristics in your tree.
Or, you could use a negative heuristic.
touch /home/kent/perl5/.path_isdev_ignore
PATH_ISDEV_DEBUG=1 \
perl -Ilib -MPath::FindDev=find_dev \
-E "say find_dev(q{/home/kent/perl5/perlbrew/perls/perl-5.19.3/lib/site_perl})"
...
[Path::IsDev=0] Matching /home/kent/perl5
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : .path_isdev_ignore exists
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : /home/kent/perl5/.path_isdev_ignore is a file
[Path::IsDev=0] - ::IsDev::IgnoreFile excludes path /home/kent/perl5
[Path::IsDev=0] no match found
...
[Path::IsDev=0] Matching /
...
[Path::IsDev=0] no match foundSuccess!
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : .path_isdev_ignore exists
[Path::IsDev=0] - ::IsDev::IgnoreFile => 1 : /home/kent/perl5/.path_isdev_ignore is a file# HEURISTICS
## Negative Heuristics bundled with this distribution
Just remember, a **Negative** Heuristic **excludes the path it is associated with**
- [`IsDev::IgnoreFile`](https://metacpan.org/pod/Path::IsDev::NegativeHeuristic::IsDev::IgnoreFile) - `.path_isdev_ignore`
## Positive Heuristics bundled with this distribution
- [`Changelog`](https://metacpan.org/pod/Path::IsDev::Heuristic::Changelog) - Files matching `Changes`, `Changelog`, and similar, case
insensitive, extensions optional.
- [`DevDirMarker`](https://metacpan.org/pod/Path::IsDev::Heuristic::DevDirMarker) - explicit `.devdir` file to indicate a project root.
- [`META`](https://metacpan.org/pod/Path::IsDev::Heuristic::META) - `META.yml`/`META.json`
- [`MYMETA`](https://metacpan.org/pod/Path::IsDev::Heuristic::MYMETA) - `MYMETA.yml`/`MYMETA.json`
- [`Makefile`](https://metacpan.org/pod/Path::IsDev::Heuristic::Makefile) - Any `Makefile` format documented supported by GNU Make
- [`TestDir`](https://metacpan.org/pod/Path::IsDev::Heuristic::TestDir) - A directory called either `t/` or `xt/`
- [`Tool::DZil`](https://metacpan.org/pod/Path::IsDev::Heuristic::Tool::DZil) - A `dist.ini` file
- [`Tool::MakeMaker`](https://metacpan.org/pod/Path::IsDev::Heuristic::Tool::MakeMaker) - A `Makefile.PL` file
- [`Tool::ModuleBuild`](https://metacpan.org/pod/Path::IsDev::Heuristic::Tool::ModuleBuild) - A `Build.PL` file
- [`VCS::Git`](https://metacpan.org/pod/Path::IsDev::Heuristic::VCS::Git) - A `.git` directory# HEURISTIC SETS
## Heuristic Sets Bundled with this distribution
- [`Basic`](https://metacpan.org/pod/Path::IsDev::HeuristicSet::Basic) - The basic heuristic set that contains most, if not all heuristics.
# ADVANCED USAGE
## Custom Sets
`Path::IsDev` has a system of "sets" of Heuristics, in order to allow for pluggable
and flexible heuristic types.Though, for the vast majority of cases, this is not required.
use Path::IsDev is_dev => { set => 'Basic' };
use Path::IsDev is_dev => { set => 'SomeOtherSet' , -as => 'is_dev_other' };## Overriding the default set
If for whatever reason the `Basic` set is insufficient, or if it false positives on your system for some reason,
the "default" set can be overridden.export PATH_ISDEV_DEFAULT_SET="SomeOtherSet"
...
use Path::IsDev qw( is_dev );
is_dev('/some/path') # uses SomeOtherSetThough this will only take priority in the event the set is not specified during `import`
If this poses a security concern for the user, then this security hole can be eliminated by declaring the set you want in code:
export PATH_ISDEV_DEFAULT_SET="SomeOtherSet"
...
use Path::IsDev is_dev => { set => 'Basic' };
is_dev('/some/path') # uses Basic, regardless of ENV# SECURITY
Its conceivable, than an evil user could construct an evil set, containing arbitrary and vulnerable code, and possibly stash that
evil set in a poorly secured privileged users @INCAnd if they managed to achieve that, if they could poison the privileged users %ENV, they could trick the privileged user into
executing arbitrary code.Though granted, if you can do either of those 2 things, you're probably security vulnerable anyway, and granted, if you could do
either of those 2 things you could do much more evil things by the following:export PERL5OPT="-MEvil::Module"
So with that in understanding, saying this modules default utility is "insecure" is mostly a bogus argument.
And to that effect, this module does nothing to "lock down" that mechanism, and this module encourages you
to **NOT** force a set, unless you **NEED** to, and strongly suggests that forcing a set for the purpose of security will achieve
no real improvement in security, while simultaneously reducing utility.# AUTHOR
Kent Fredric
# COPYRIGHT AND LICENSE
This software is copyright (c) 2017 by Kent Fredric .
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.