V-0.22/0000755000031300001440000000000014744365200011104 5ustar00merijnusersV-0.22/MANIFEST.SKIP0000644000031300001440000000025014736461346013010 0ustar00merijnusers.aspell.local.pws blib/ xt/ core-t/ debian/ doc/ sandbox/ Makefile$ Makefile.bak make-doc\.pl MYMETA\. pm_to_blib \..+\.swp$ \.git \.git(ignore|attributes) gz$ ^V\.pm$ V-0.22/t/0000755000031300001440000000000014744365177011364 5ustar00merijnusersV-0.22/t/lib/0000755000031300001440000000000014744365177012132 5ustar00merijnusersV-0.22/t/lib/V_Version.pm0000644000031300001440000000006614660054263014370 0ustar00merijnuserspackage V_Version; $V_Version::VERSION = v1.2.3; 1; V-0.22/t/lib/PkgWithVersion.pm0000644000031300001440000000004114660054263015372 0ustar00merijnuserspackage PkgWithVersion 0.42; 1; V-0.22/t/lib/GH/0000755000031300001440000000000014744365177012430 5ustar00merijnusersV-0.22/t/lib/GH/Issue1.pm0000644000031300001440000000010214660054263014114 0ustar00merijnusersour $VERSION = '1.1'; package Foo 1.2; package GH::Issue1 1.3; V-0.22/t/lib/GH/ClassIssue1.pm0000644000031300001440000000003714660054263015111 0ustar00merijnusersclass GH::ClassIssue1 0.42 { } V-0.22/t/lib/Misleading/0000755000031300001440000000000014744365177014206 5ustar00merijnusersV-0.22/t/lib/Misleading/GetVersion.pm0000644000031300001440000000015314660054263016614 0ustar00merijnuserspackage Misleading::GetVersion; use Misleading::Version; our $VERSION = Misleading::Version->VERSION; 1; V-0.22/t/lib/Misleading/Version.pm0000644000031300001440000000006714660054263016160 0ustar00merijnuserspackage Misleading::Version; our $VERSION = 0.42; 1; V-0.22/t/lib/Misleading.pm0000644000031300001440000000033414660054263014530 0ustar00merijnuserspackage Misleading; use vars qw< $VERSION >; $VERSION = 0.42; my ($major, $minor) = $VERSION =~ m/(\d+)(?:\.(\d+))?/; my %opt = (); %opt = ( package => (exists($opt{package}) ? $opt{package} : (caller)[0]), ); 1; V-0.22/t/lib/PkgWithVersion2.pm0000644000031300001440000000005514660054263015461 0ustar00merijnuserspackage PkgWithVersion2 v1.42.00 { 1; } V-0.22/t/lib/ModExtVSN.pm0000644000031300001440000000424414744364640014255 0ustar00merijnusers#!/usr/bin/perl # Cut down and tidied copy from Module::Extract::VERSION-1.117 # to catch $VERSION inside single quotes require v5.10; package ModExtVSN; use strict; use warnings; no warnings; use Carp qw(carp); # This is the correct version vvv our $VERSION = '1.25'; =encoding utf8 =head1 NAME Module::Extract::VERSION - Extract a module version safely =head1 SYNOPSIS use Module::Extract::VERSION; my $version # just the version = Module::Extract::VERSION->parse_version_safely( $file ); my @version_info # extra info = Module::Extract::VERSION->parse_version_safely( $file ); =cut sub parse_version_safely { my ($class, $file) = @_; local $/ = "\n"; local $_; # don't mess with the $_ in the map calling this my $fh; unless (open $fh, "<", $file) { carp ("Could not open file [$file]: $!\n"); return; } my $in_pod = 0; my ($sigil, $var, $version, $line_number, $rhs); while (<$fh>) { $line_number++; chomp; $in_pod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $in_pod; next if $in_pod || /^\s*#/; # package NAMESPACE VERSION <-- we handle that # package NAMESPACE VERSION BLOCK next unless / (? [\$*] ) (? (? [\w\:\']* ) \b VERSION ) \b .*? \= (? .* ) /x || m/ \b package \s+ (? \w[\w\:\']* ) \s+ (? \S+ ) \s* [;{] /x; ($sigil, $var, $rhs) = @+{qw(sigil var rhs)}; if ($sigil) { $version = $class->_eval_version ($_, @+{qw(sigil var rhs)}); } else { $version = $class->_eval_version ($_, '$', 'VERSION', qq('$rhs')); } last; } $line_number = undef if eof ($fh) && !defined ($version); close $fh; return wantarray ? ($sigil, $var, $version, $file, $line_number) : $version; } sub _eval_version { my ($class, $line, $sigil, $var, $rhs) = @_; require Safe; require version; local $^W = 0; my $s = Safe->new; if (defined $Devel::Cover::VERSION) { $s->share_from ('main', ['&Devel::Cover::use_file']); } # These lines should be ignored vvv $s->reval ('$VERSION = ' . $rhs); my $version = $s->reval ('$VERSION'); return $version; } 1; V-0.22/t/02useit.t0000755000031300001440000000143114660065147013035 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; $| = 1; package Catch; sub TIEHANDLE { bless \(my $self), shift } sub PRINT { my $self = shift; $$self .= $_[0] } sub PRINTF { my $self = shift; my $format = shift; $$self .= sprintf $format, @_; } # PRINTF package main; require_ok ("V"); local *CATCHOUT; my $out = tie *CATCHOUT, "Catch"; my $stdout = select CATCHOUT; $V::NO_EXIT = 1; V->import ("V"); select $stdout; ok ($$out, "V->import() produced output"); like ($$out, qr/^V\n/, "Module is V"); like ($$out, qr/^\t(.+?)V\.pm: $V::VERSION$/m, "VERSION is $V::VERSION"); is ($V::NO_EXIT, 1, "Packagevar \$V::NO_EXIT set"); is (V::get_version ("V"), $V::VERSION, "get_version()"); abeltje_done_testing (); V-0.22/t/05_pkgwithversion.t0000644000031300001440000000063314660065440015125 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; SKIP: { $] < 5.012 and skip ("This perl is not >= 5.12.0", 3); require_ok ("V"); my $version = V::get_version ("PkgWithVersion"); is ($version, 0.42, "Got version: $version"); my $version2 = V::get_version ("PkgWithVersion2"); is ($version2, "v1.42.00", "Got version: $version2"); } abeltje_done_testing (); V-0.22/t/06_multi_version.t0000644000031300001440000000273714660065704014754 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; use Cwd "abs_path"; use File::Spec::Functions; require_ok ("V"); { my $version; my $warning = warning { $version = V::get_version ("GH::Issue1"); }; is ($version, "1.3", "Find specific version"); if ($] < 5.012) { is_deeply ( $warning, [ qq{Your perl doesn't understand the version declaration of Foo\n}, qq{Your perl doesn't understand the version declaration of GH::Issue1\n}, ], "Found warning for perl $]") or diag (explain ($warning)); } else { is_deeply ($warning, [], "No warnings for perl $]") or diag (explain ($warning)); } } { my ($stdout, $warning); { no warnings "once"; local *STDOUT; open *STDOUT, ">>", \$stdout; local $V::NO_EXIT = 1; local @INC = "t/lib"; $warning = warning { V->import ("GH::Issue1") }; } is ($stdout, <<"EOT", "All packages in output") or diag ("STDOUT: $stdout"); GH::Issue1 \t@{[canonpath (catfile (abs_path ("."), qw( t lib GH Issue1.pm )))]}: \t main: 1.1 \t Foo: 1.2 \t GH::Issue1: 1.3 EOT if ($] < 5.012) { is_deeply ( $warning, [ qq{Your perl doesn't understand the version declaration of Foo\n}, qq{Your perl doesn't understand the version declaration of GH::Issue1\n}, ], "Found warning for perl $]" ) or diag (explain ($warning)); } else { is_deeply ($warning, [], "No warnings for perl $]") or diag (explain ($warning)); } } abeltje_done_testing (); V-0.22/t/07_class_version.t0000644000031300001440000000076714660066374014735 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; { require_ok ("V"); my $version; my $warning = warning { $version = V::get_version ("GH::ClassIssue1"); }; is ($version, "0.42", "Class also works"); if ($] < 5.012) { like ( $warning, qr{^Your perl .+ GH::ClassIssue1}, "Found warning for perl $]" ); } else { is_deeply ($warning, [], "No warnings for perl $]") or diag (explain ($warning)); } } abeltje_done_testing (); V-0.22/t/01basic.t0000755000031300001440000000136614660065147012773 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; require_ok ("V"); ok ($V::VERSION, '$V::VERSION is there'); SKIP: { local $ENV{PERL5OPT} = -d "blib" ? "-Mblib" : "-Mlib=lib"; local *PIPE; my $out; if (open PIPE, qq!$^X -MV |!) { $out = do { local $/; }; unless (close PIPE) { if (open PIPE, qq!$^X -I. -e "use V;" |!) { $out = do { local $/; }; skip "Error in pipe(2): $! [$?]", 1 unless close PIPE; } else { skip "Could not fork: $!", 1; } $out or skip "Error in pipe(1): $! [$?]", 1; } } else { skip "Could not fork: $!"; } my ($version) = $out =~ /^.+?([\d._]+)$/m; is ($version, $V::VERSION, "Version ok ($version)"); } abeltje_done_testing (); V-0.22/t/03bug.t0000644000031300001440000000054314660065230012453 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; require_ok ("V"); my @modules = map { s{/}{::}g; s{\.pm$}{}; $_; } grep { m/\.pm$/ && !m/^Config\.pm$/ } keys %INC; my $versions = eval { join ", " => map { "$_: " . V::get_version ($_) } qw( Cwd ); }; is ($@, "", "readonly bug"); abeltje_done_testing (); V-0.22/t/04v_version.t0000644000031300001440000000032314660065270013711 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; require_ok ("V"); my $version = V::get_version ("V_Version"); is ($version, "v1.2.3", "Got version: $version"); abeltje_done_testing (); V-0.22/t/Test/0000755000031300001440000000000014744365177012303 5ustar00merijnusersV-0.22/t/Test/abeltje.pm0000644000031300001440000000326014736464314014242 0ustar00merijnusers#!/usr/bin/perl package t::Test::abeltje; use 5.014000; use strict; use warnings; our $VERSION = "1.09"; use parent "Test::Builder::Module"; use Test::Builder::Module; use Test::More; use Test::Fatal qw( exception success dies_ok lives_ok ); use Test::Warnings qw( :all ); our @EXPORT = ( "abeltje_done_testing", @Test::More::EXPORT, @Test::Fatal::EXPORT_OK, @Test::Warnings::EXPORT_OK, ); sub import_extra { # use Test::Warnings 'warnings' interferes # with warnings->import() warnings::import ("warnings"); strict->import (); require feature; feature->import (":5.10"); require lib; lib->import ("t/lib"); $Devel::Cover::VERSION and # don't run_end_test when Devel::Cover Test::Warnings->import (":no_end_test"); $ENV{AUTHOR_TESTING} or Test::Warnings->import (":no_end_test"); } *abeltje_done_testing = \&Test::More::done_testing; 1; =head1 NAME t::Test::abeltje - Helper Test module that imports useful stuff. =head1 SYNOPSIS #! perl -I. use t::Test::abeltje; # Do not forget -I. on the shebang line # this is where you have your Fav. test-routines. abeltje_done_testing (); =head1 DESCRIPTION Mostly nicked from other modules (like L)... This gives you L, L, L and also imports for you: L, L, the L with the C<:5.10> tag and L with the C path. =head2 abeltje_done_testing Just for fun, an alias for L. =head2 import_extra This module works by the use of L. =head1 COPYRIGHT E MMXX - Abe Timmerman =cut V-0.22/t/08_misleading.t0000644000031300001440000000066414744364656014203 0ustar00merijnusers#!/usr/bin/perl -I. use strict; use warnings; use t::Test::abeltje; require_ok ("V"); { my $version = V::get_version ("Misleading"); is ($version, 0.42, "Misleading version"); } { my $version = V::get_version ("Misleading::GetVersion"); is ($version, 0.42, "Another misleading version"); } { my $version = V::get_version ("ModExtVSN"); is ($version, 1.25, "Ignored eval"); } abeltje_done_testing (); V-0.22/SECURITY.md0000644000031300001440000000760014736763717012720 0ustar00merijnusers# Security Policy for the V distribution. Report issues via email at: H.Merijn Brand . This is the Security Policy for the Perl V distribution. The latest version of the Security Policy can be found in the [git repository for V](https://github.com/Tux/V). This text is based on the CPAN Security Group's Guidelines for Adding a Security Policy to Perl Distributions (version 1.0.0) https://security.metacpan.org/docs/guides/security-policy-for-authors.html # How to Report a Security Vulnerability Security vulnerabilities can be reported by e-mail to the current project maintainers at H.Merijn Brand . Please include as many details as possible, including code samples or test cases, so that we can reproduce the issue. Check that your report does not expose any sensitive data, such as passwords, tokens, or personal information. If you would like any help with triaging the issue, or if the issue is being actively exploited, please copy the report to the CPAN Security Group (CPANSec) at . Please *do not* use the public issue reporting system on RT or GitHub issues for reporting security vulnerabilities. Please do not disclose the security vulnerability in public forums until past any proposed date for public disclosure, or it has been made public by the maintainers or CPANSec. That includes patches or pull requests. For more information, see [Report a Security Issue](https://security.metacpan.org/docs/report.html) on the CPANSec website. ## Response to Reports The maintainer(s) aim to acknowledge your security report as soon as possible. However, this project is maintained by a single person in their spare time, and they cannot guarantee a rapid response. If you have not received a response from them within 10 days, then please send a reminder to them and copy the report to CPANSec at . Please note that the initial response to your report will be an acknowledgement, with a possible query for more information. It will not necessarily include any fixes for the issue. The project maintainer(s) may forward this issue to the security contacts for other projects where we believe it is relevant. This may include embedded libraries, system libraries, prerequisite modules or downstream software that uses this software. They may also forward this issue to CPANSec. # Which Software This Policy Applies To Any security vulnerabilities in V are covered by this policy. Security vulnerabilities are considered anything that allows users to execute unauthorised code, access unauthorised resources, or to have an adverse impact on accessibility or performance of a system. Security vulnerabilities in upstream software (embedded libraries, prerequisite modules or system libraries, or in Perl), are not covered by this policy unless they affect V, or V can be used to exploit vulnerabilities in them. Security vulnerabilities in downstream software (any software that uses V, or plugins to it that are not included with the V distribution) are not covered by this policy. ## Supported Versions of V The maintainer(s) will only commit to releasing security fixes for the latest version of V. Note that the V project only supports major versions of Perl released in the past 5 years, even though V will run on older versions of Perl. If a security fix requires us to increase the minimum version of Perl that is supported, then we may do so. # Installation and Usage Issues The distribution metadata specifies minimum versions of prerequisites that are required for V to work. However, some of these prerequisites may have security vulnerabilities, and you should ensure that you are using up-to-date versions of these prerequisites. Where security vulnerabilities are known, the metadata may indicate newer versions as recommended. ## Usage Please see the software documentation for further information. V-0.22/Changes0000644000031300001440000001411114744365155012406 0ustar00merijnusers0.22 2025-01-23 H.Merijn Brand - Add SECURITY.md - Add CONTRIBUTING.md - Ignore $VERSION inside single quotes 0.21 2025-01-05 H.Merijn Brand - remove xt/ from dist - require 5.14.0 0.20 2025-01-03 H.Merijn Brand - This release is in fond memories of Abe Timmerman - New maint - Add cpanfile - Include xt in "make test" for dev - Rewrote Changes to reflect actual work 0.19 2024-01-08 Abe Timmerman - Found another exception: Devel::PPPort 0.18 2023-11-22 Abe Timmerman - FIX: the regexen to identify versions - Show only packages/classes with a defined version 0.17 2023-11-11 Abe Timmerman - Add the debian/ directory. - Change the bugtracker to GitHub. - Take package $version over $VERSION=$version for 5.12+ (issue#1) - Add class versions of package - Show all packages/classes in a file - Portable path (File::Spec) 0.16 2022-05-26 Abe Timmerman - Add check for new version syntax: We now support the `package Blah 0.42` syntax. - Update version in README.md 0.15 2021-05-13 Abe Timmerman - Update tester module 0.14 2021-05-11 Abe Timmerman - After reading the Test::Warnings docs (again) the CPANTesters errors were to be expected - Fix more things for MSWin32 - Update dependencies - Add t::Test::abeltje - This needed some kwalitee changes, mostly in POD 0.00 2003-03-09 Abe Timmerman - (abeltje, Sun, 9 Mar 2003 23:16:24 +0000) Create space for the V module - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@64 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Sun, 9 Mar 2003 23:17:33 +0000) Initial import of V-0.06 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@65 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Sun, 9 Mar 2003 23:37:05 +0000) Change the way we C<< use lib $lib; >> for Test-More - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@66 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Sun, 9 Mar 2003 23:38:13 +0000) $VERSION += 0.01 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@67 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Sun, 9 Mar 2003 23:40:16 +0000) $VERSION += 0.01 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@68 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 22 Aug 2003 01:46:32 +0000) * [REMOVE] No more Test::More, make it a PREREQ - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@70 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 22 Aug 2003 01:49:41 +0000) * [FIX] make the tests pass again - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@71 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 22 Aug 2003 01:51:06 +0000) * [CHANGE] - general cleanup and $VERSION += 0.01 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@72 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 22 Aug 2003 01:53:24 +0000) * [PRIVATE] do the ChangeLog/Changes dance - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@73 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 16 Jan 2004 12:58:27 +0000) * [FIX] by Merijn Brand - fix a syntax error in the PREREQ_PM target - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@74 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 16 Jan 2004 13:09:03 +0000) * [ADD] - feature request by Merijn Brand: - Can you add a sub that returns the version only for a given module - added a test for V::get_version - VERSION += 0.01 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@75 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 16 Jan 2004 13:13:13 +0000) * regen Changes for 0.09 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@76 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Wed, 24 Mar 2004 06:43:27 +0000) * [CHANGE] - added the license stuff - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@77 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Wed, 24 Mar 2004 06:44:42 +0000) * Regen Changes for 0.10 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@78 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 3 Feb 2006 16:04:17 +0000) * [CHANGE] - add untainting stuff by Stas Bekman (2004/03/24) - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@79 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 3 Feb 2006 17:07:51 +0000) * Regenerate Changes for V 0.11 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@80 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 31 Mar 2006 14:03:49 +0000) * [PRIVATE] - redo 01basic.t for core - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@82 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 31 Mar 2006 15:28:21 +0000) * [CHANGE] - small rework of the AUTHOR/LICENSE sections in pod - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@83 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Fri, 31 Mar 2006 15:29:56 +0000) * [CORE] - put the tests for the core-distribution in their own directory - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@84 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Wed, 7 Nov 2007 00:10:02 +0000) * [CHANGE] - FIX: bug reported by Merijn: - my $version = map { "$_ " . V::get_version( $_ ) } qw/ Cwd /; - "Modification of a read-only value attempted" - local()ize $_ before reading the file to find the version - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@85 03e79c58-f747-0410-a819-f71e7ca513d9 - (abeltje, Wed, 7 Nov 2007 00:11:35 +0000) * Regenerate Changes for V 0.13 - git-svn-id: https://source.test-smoke.org/repos/cpan/trunk/V@86 03e79c58-f747-0410-a819-f71e7ca513d9 - (Abe Timmerman, Wed, 5 May 2021 23:38:36 +0200) Fix bug with v-strings and update repository - Whenever a module used a v-string-version the module would return undef, - we now use the core module 'version' to make sure we also return a - version for these cases. - Moved V.pm to the lib/ directory - Moved README to README.md and added some markdown - added a .gitignore and MANIFEST.SKIP - (Abe Timmerman, Thu, 6 May 2021 00:14:28 +0200) Fix test to also run under 'prove' V-0.22/lib/0000755000031300001440000000000014744365177011667 5ustar00merijnusersV-0.22/lib/V.pm0000644000031300001440000002227514744365075012437 0ustar00merijnuserspackage V; require 5.014000; use strict; use warnings; use vars qw( $VERSION $NO_EXIT ); $VERSION = "0.22"; $NO_EXIT ||= 0; # prevent import() from exit()ing and fall of the edge our $DEBUG; $DEBUG ||= $ENV{PERL_V_DEBUG} || 0; =encoding utf-8 =head1 NAME V - Print version of the specified module(s). =head1 SYNOPSIS $ perl -MV=V or if you want more than one $ perl -MV=CPAN,V Can now also be used as a light-weight module for getting versions of modules without loading them: require V; printf "%s has version '%s'\n", "V", V::get_version ("V"); Starting with version B<0.17>, V will show all Cs or Ces in a file that have a version. If one wants to see all packages/classes from that file, set the environment variable C to a I value. If you want all available files/versions from C<@INC>: require V; my @all_V = V::Module::Info->all_installed ("V"); printf "%s:\n", $all_V[0]->name; for my $file (@all_V) { my ($versions) = $file->version; # Must be list context if (@$versions > 1) { say "\t", $file->name; print "\t %-30s: %s\n", $_->{pkg}, $_->{version} for @versions; } else { printf "\t%-50s - %s\n", $file->file, $versions->[0]{version}; } } Each element in that array isa C object with 3 attributes and a method: =over =item I B The package name. =item I B Full filename with directory. =item I B The base directory (from C<@INC>) where the package-file was found. =item I B This method will look through the file to see if it can find a version assignment in the file and uses that to determine the version. As of version B<0.13_01>, all versions found are passed through the L module. As of version B<0.16_03> we look for all types of version declaration: package Foo; our $VERSION = 0.42; and package Foo 0.42; and package Foo 0.42 { ... } Not only do we look for the C keyword, but also for C. In list context this method will return an arrayref to a list of structures: =over 8 =item I The name of the C/C. =item I The version for that C/C. (Can be absent if C<$PERL_V_SHOW_ALL> is true.) =item I The ordinal number of occurrence in the file. =back =back =head1 DESCRIPTION This module uses stolen code from L to find the location and version of the specified module(s). It prints them and exit()s. It defines C and is based on an idea from Michael Schwern on the perl5-porters list. See the discussion: https://www.nntp.perl.org/group/perl.perl5.porters/2002/01/msg51007.html =head2 V::get_version($pkg) Returns the version of the first available file for this package as found by following C<@INC>. =head3 Arguments =over =item 1. $pkg The name of the package for which one wants to know the version. =back =head3 Response This C returns the version of the file that was first found for this package by following C<@INC> or C if no file was found. =begin implementation =head2 report_pkg This sub prints the results for a package. =head3 Arguments =over =item 1. $pkg The name of the package that was probed for versions =item 2. @versions An array of Module-objects with full path and version. =back =end implementation =head1 SEE ALSO There are numerous module on CPAN that (try to) extract the VERSION from modules. L maybe being th most important inspiration. L was used to copy code from. =head1 AUTHOR Abe Timmerman -- 2002 - 2024 (✝ 2024-08-15 😢) H.Merijn Brand C<< >> (2024 ...) =head1 COPYRIGHT AND LICENSE Copyright 2024-2025 H.Merijn Brand, All Rights Reserved. Copyright 2002-2024 Abe Timmerman, All Rights Reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-ABILITY or FITNESS FOR A PARTICULAR PURPOSE. =cut sub report_pkg ($@) { my $pkg = shift; print "$pkg\n"; @_ or print "\tNot found\n"; foreach my $module (@_) { my ($versions) = $module->version; if (@$versions > 1) { printf "\t%s:\n", $module->file; printf "\t %s: %s\n", $_->{pkg}, $_->{version} || '' for @$versions; } else { printf "\t%s: %s\n", $module->file, $versions->[0]{version} || '?'; } } } # report_pkg sub import { shift; @_ or push @_ => 'V'; for my $pkg (@_) { my @modules = V::Module::Info->all_installed ($pkg); report_pkg $pkg, @modules; } $NO_EXIT or exit (); } # import sub get_version { my ($pkg) = @_; my ($first) = V::Module::Info->all_installed ($pkg); return $first ? $first->version : undef; } # get_version caller or V->import (@ARGV); 1; # Okay I did the AUTOLOAD bit, but this is a Copy 'n Paste job. # Thank you Michael Schwern for Module::Info! This one is mostly that! package V::Module::Info; require File::Spec; sub new_from_file { my ($proto, $file) = @_; my $class = ref $proto || $proto; -r $file and return bless { file => File::Spec->rel2abs ($file), dir => "", name => "", } => $class; } # new_from_file sub all_installed { my ($proto, $name, @inc) = @_; my $class = ref $proto || $proto; @inc or @inc = @INC; my $file = File::Spec->catfile (split m/::/ => $name) . ".pm"; my @modules; foreach my $dir (@inc) { # Skip the new code ref in @INC feature. ref $dir and next; my $filename = File::Spec->catfile ($dir, $file); -r $filename or next; my $module = $class->new_from_file ($filename); $module->{dir} = File::Spec->rel2abs ($dir); $module->{name} = $name; push @modules => $module; } $V::DEBUG and do { print {*STDERR} "# $file: @{[scalar $_->version]}\n" for @modules }; return @modules; } # all_installed # Once thieved from ExtUtils::MM_Unix 1.12603 # Stealing from Module::Extract::VERSION is an option for the future sub version { my $self = shift; my $parsefile = $self->file; open my $mod, "<", $parsefile or die "open $parsefile: $!"; my $inpod = 0; local $_; my %eval; my ($cur_pkg, $cur_ord) = ("main", 0); $eval{$cur_pkg} = { ord => $cur_ord }; while (<$mod>) { $inpod = m/^=(?!cut)/ ? 1 : m/^=cut/ ? 0 : $inpod; $inpod || m/^\s*#/ and next; chomp; if (m/^\s* (?:package|class) \s+ (\w+(?:::\w+)*) /x) { $cur_pkg = $1; exists $eval{$cur_pkg} or $eval{$cur_pkg} = { ord => ++$cur_ord }; } $cur_pkg =~ m{^V::Module::Info} and next; if (m/(?:our)?\s*([\$*])(([\w\:\']*)\bVERSION)\s*\=(?![=~])/) { { local ($1, $2); ($_ = $_) = m/(.*)/; } # untaint my ($sigil, $name) = ($1, $2); m/\$$name\s*=\s*eval.+\$$name/ and next; m/my\s*\$VERSION\s*=/ and next; m/^[^']*'[^']*\$$name[^']*'/ and next; $eval{$cur_pkg}{prg} = qq{ package V::Module::Info::_version_var; # $cur_pkg no strict; local $sigil$name; \$$name = undef; do { $_ # Closing brace needs to be on next line # as toping can haz comment }; \$$name }; } # perl 5.12.0+ elsif (m/^\s* (?:package|class) \s+ [^\s]+ \s+ (v?[0-9.]+) \s* [;\{]/x) { my $ver = $1; if ($] >= 5.012000) { $eval{$cur_pkg}{prg} = qq{ package V::Module::Info::_version_static $ver; # $cur_pkg V::Module::Info::_version_static->VERSION; }; } else { warn "Your perl doesn't understand the version declaration of $cur_pkg\n"; $eval{$cur_pkg}{prg} = qq{ $ver }; } } } close $mod; # remove our stuff delete $eval{$_} for grep { m/^V::Module::Info/ } keys %eval; my @results; while (my ($pkg, $dat) = each %eval) { my $result; if ($dat->{prg}) { $V::DEBUG and warn "# $pkg: $dat->{prg}\n"; local $^W = 0; $result = eval $dat->{prg}; $V::DEBUG && $@ and warn "Could not eval '$dat->{prg}' in $parsefile: $@"; # use the version modulue to deal with v-strings require version; $dat->{ver} = $result = version->parse ($result); } push @results => { (exists $dat->{ver} ? (version => $result) : ()), pkg => $pkg, ord => $dat->{ord}, }; } $ENV{PERL_V_SHOW_ALL} or @results = grep { exists ($_->{version}) } @results; @results > 1 and @results = grep { $_->{pkg} ne "main" || exists $_->{version} } @results; unless (wantarray) { foreach my $option (@results) { $option->{pkg} eq $self->name or next; return $option->{version}; } return; } return [ sort { $a->{ord} <=> $b->{ord} } @results ]; } # version sub accessor { my $self = shift; my $field = shift; @_ and $self->{$field} = $_[0]; return $self->{$field}; } # accessor sub AUTOLOAD { my ($self) = @_; use vars qw( $AUTOLOAD ); my ($method) = $AUTOLOAD =~ m{.+::(.+)$}; if (exists $self->{$method}) { splice @_, 1, 0, $method; goto &accessor; } } # AUTOLOAD 1; V-0.22/cpanfile0000644000031300001440000000053514744365200012613 0ustar00merijnusersrequires "File::Spec"; on "configure" => sub { requires "ExtUtils::MakeMaker"; recommends "ExtUtils::MakeMaker" => "7.70"; }; on "test" => sub { requires "Test::Fatal"; requires "Test::Simple" => "0.88"; requires "Test:Warnings"; recommends "Test::Simple" => "1.302207"; }; V-0.22/Makefile.PL0000644000031300001440000000350514736465233013071 0ustar00merijnusers#!/usr/bin/perl use 5.014000; use strict; use warnings; use ExtUtils::MakeMaker; WriteMakefile ( NAME => "V", VERSION_FROM => "lib/V.pm", ABSTRACT_FROM => "lib/V.pm", AUTHOR => 'H.Merijn Brand ', TEST_REQUIRES => { "Test::Simple" => 0.88, "Test::Fatal" => 0, "Test::Warnings" => 0, }, PREREQ_PM => { version => 0.77, }, macro => { TARFLAGS => "--format=ustar -c -v -f", }, MIN_PERL_VERSION => "5.010001", LICENSE => "perl_5", META_ADD => { "meta-spec" => { version => 2, }, "resources" => { homepage => "https://github.com/Tux/V", repository => { type => "git", url => "https://github.com/Tux/V.git", }, bugtracker => { web => "https://github.com/Tux/V/issues", }, x_IRC => 'irc://irc.perl.org/#csv', }, }, ); 1; package MY; sub postamble { my $do_xt = (-d "xt" && ($ENV{AUTOMATED_TESTING} || 0) != 1) ? join "\n" => 'test ::', ' -@env TEST_FILES="xt/*.t" make -e test_dynamic', ' -perl doc/make-doc.pl', '' : ""; join "\n" => 'cover $make_sep test_cover:', ' ccache -C', ' -@rm -f *.gc??', ' cover -test', ' cover -report html_basic', '', 'spellcheck:', ' pod-spell-check --aspell --ispell', '', 'checkmeta: spellcheck', ' perl sandbox/genMETA.pl -c', '', 'fixmeta: distmeta', ' perl sandbox/genMETA.pl', '', 'tgzdist: checkmeta fixmeta $(DISTVNAME).tar.gz distcheck', ' -@mv -f $(DISTVNAME).tar.gz $(DISTVNAME).tgz', ' -@cpants_lint.pl $(DISTVNAME).tgz', ' -@rm -f Debian_CPANTS.txt', ' -@echo "Consider running sandbox/used-by.pl now"', '', 'test_used: test', ' prove -vwb sandbox/used-by.pl', '', 'doc docs:', ' perl doc/make-doc.pl', '', $do_xt; } # postamble V-0.22/README.md0000644000031300001440000000362014736463751012377 0ustar00merijnusers# **V** This module uses stolen code from [`Module::Info`](https://metacpan.org/pod/Module::Info) to find the location and version of the specified module(s). It prints them and exit()s. It works by definening `import()` and is based on an idea from Michael Schwern on the perl5-porters list. See [the discussion](https://www.nntp.perl.org/group/perl.perl5.porters/2002/01/msg51007.html) ```bash 🐧 perl -MV=CPAN CPAN /pro/lib/perl5/site_perl/5.40.0/CPAN.pm: 2.38 /pro/lib/perl5/5.40.0/CPAN.pm: 2.36 ``` or if you want more than one package ```bash 🐧 perl -MV=CPAN,V ``` As of version **0.17** it will show all `package`s and `class`es in a file with a version. (If one wants *all* packages/classes in the files, set the environment variable `PERL_V_SHOW_ALL`) ```bash 🐧 perl -MV=SOAP::Lite SOAP::Lite /pro/lib/perl5/site_perl/5.40.0/SOAP/Lite.pm: SOAP::Lite: 1.27 SOAP::Client: 1.27 ``` # INSTALLATION To install this module type the following commands: - `perl Makefile.PL` - `make test` - `make install` # DEPENDENCIES This module requires no extra modules or libraries from perl version 5.14.0 (exept [`Test::More`](https://metacpan.org/pod/Test::More), [`Test::Warnings`](https://metacpan.org/pod/Test::Warnings), [`Test::Fatal`](https://metacpan.org/pod/Test::Fatal) for the test-suite). # SEE ALSO To get more info on the programming interface see [`perldoc V`](https://metacpan.org/pod/V) # COPYRIGHT © 2002..2024 Abe Timmerman . All rights reserved. © 2024..2025 H.Merijn Brand . All rights reserved. # LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. 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. V-0.22/CONTRIBUTING.md0000644000031300001440000000201414736764106013343 0ustar00merijnusers# General I am always open to improvements and suggestions. Use [issues](https://github.com/Tux/V/issues) # Style I will never accept pull request that do not strictly conform to my style, however you might hate it. You can read the reasoning behind my [preferences](http://tux.nl/style.html). I really do not care about mixed spaces and tabs in (leading) whitespace Perl::Tidy will help getting the code in shape, but as all software, it is not perfect. You can find my preferences for these in [.perltidy](https://github.com/Tux/Release-Checklist/blob/master/.perltidyrc) and [.perlcritic](https://github.com/Tux/Release-Checklist/blob/master/.perlcriticrc). # Mail Please, please, please, do *NOT* use HTML mail. [Plain text](https://useplaintext.email) [without](http://www.goldmark.org/jeff/stupid-disclaimers/) [disclaimers](https://www.economist.com/business/2011/04/07/spare-us-the-e-mail-yada-yada) will do fine! # Requirements The minimum version required to use this module is stated in [Makefile.PL](./Makefile.PL) V-0.22/MANIFEST0000644000031300001440000000116214744365200012235 0ustar00merijnusersChanges lib/V.pm Makefile.PL CONTRIBUTING.md SECURITY.md MANIFEST MANIFEST.SKIP README.md cpanfile t/01basic.t t/02useit.t t/03bug.t t/04v_version.t t/05_pkgwithversion.t t/06_multi_version.t t/07_class_version.t t/08_misleading.t t/lib/GH/ClassIssue1.pm t/lib/GH/Issue1.pm t/lib/Misleading.pm t/lib/Misleading/GetVersion.pm t/lib/Misleading/Version.pm t/lib/ModExtVSN.pm t/lib/PkgWithVersion.pm t/lib/PkgWithVersion2.pm t/lib/V_Version.pm t/Test/abeltje.pm META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) V-0.22/META.yml0000644000031300001440000000137614744365200012364 0ustar00merijnusers--- abstract: Print version of the specified module(s) author: - H.Merijn Brand - Abe Timmerman configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: Author, CPAN::Meta::Converter version 2.150010 license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: V provides: V: file: lib/V.pm version: '0.22' recommends: Test::Simple: '1.302207' requires: File::Spec: 0 Test::Fatal: 0 Test::Simple: '0.88' perl: '5.014000' resources: IRC: irc://irc.perl.org/#csv bugtracker: https://github.com/Tux/V/issues homepage: https://metacpan.org/pod/V license: http://dev.perl.org/licenses/ repository: https://github.com/Tux/V version: '0.22' V-0.22/META.json0000644000031300001440000000272114744365200012527 0ustar00merijnusers{ "name" : "V", "author" : [ "H.Merijn Brand ", "Abe Timmerman" ], "resources" : { "homepage" : "https://metacpan.org/pod/V", "bugtracker" : { "web" : "https://github.com/Tux/V/issues" }, "repository" : { "type" : "git", "web" : "https://github.com/Tux/V", "url" : "https://github.com/Tux/V" }, "license" : [ "http://dev.perl.org/licenses/" ], "x_IRC" : "irc://irc.perl.org/#csv" }, "release_status" : "stable", "abstract" : "Print version of the specified module(s)", "provides" : { "V" : { "file" : "lib/V.pm", "version" : "0.22" } }, "meta-spec" : { "version" : 2, "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec" }, "dynamic_config" : 1, "prereqs" : { "runtime" : { "requires" : { "perl" : "5.014000", "File::Spec" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" }, "recommends" : { "ExtUtils::MakeMaker" : "7.70" } }, "test" : { "requires" : { "Test::Simple" : "0.88", "Test::Fatal" : "0" }, "recommends" : { "Test::Simple" : "1.302207" } } }, "license" : [ "perl_5" ], "version" : "0.22", "generated_by" : "Author" }