File-ConfigDir-0.017/000755 000765 000024 00000000000 12517443326 014213 5ustar00snostaff000000 000000 File-ConfigDir-0.017/Changes000644 000765 000024 00000004645 12517417527 015523 0ustar00snostaff000000 000000 Revision history for Perl module File::ConfigDir 0.017 2015-04-27 - add irc channel and mailing list to meta data - apply fix regarding "Cwd::abs_path is not portable" from jddurand 0.016 2015-02-06 - Update copyright year - use FindBin instead of $0 (suggested by Tina Müller via RT#101699) - style fixes - metadata updates and tweaks 0.015 2014-11-25 - replace README by README.md for better welcome on eg. GitHub - improve related author test 0.014 2014-11-11 - Rework Makefile.PL and add more author tests - fix typo in pod - Update README - Installation instructions (contributed by Martin McGrath) 0.013 2014-04-28 - fix upcoming LMU preparation (keep L::MU a recommendation) 0.012 2014-03-21 - prepare for upcoming List::MoreUtils 0.4xx 0.011 2014-01-06 - add forgotton 0.010 Changelog 0.010 2014-01-06 - bump copyright year - improve acknowledgements - rely on BAIL_OUT of Test::More instead of simulating it 0.009 2013-10-25 - add API to allow plugins to improve registration (speeds up loading) - switch to ExtUtils::MakeMaker, 'cause Module::Build had trouble with recent meta spec ... 0.008 2013-10-19 - introduce pluggable dir sources - add developer requires for runs from repository clones 0.007 2013-09-21 - Update copyright year (just to make sure everybody recognizes) 0.006 2013-09-20 - Reformatted as per CPAN::Changes::Spec by Neil Bowers - Fix rt#88616 (test didn't work according to XDG Base Directory Specification) - thanks to Alex Hartmaier. - Fix typo in regex for testing the amount of expected directories - Improve documentation 0.005 2013-09-03 - move to GitHub - fix xdg_config_dir/xdg_config_home - commit fox for rt#69263 (includes fix for rt#82696) 0.004 2010-07-30 - make helper function uniq private (_uniq) to avoid Pod::Coverage test fail on systems without List::MoreUtils 0.003 2010-07-30 - fix typo and use here_cfg_dir instead of user_cfg_dir twice - add singleapp_cfg_dir and locallib_cfg_dir to free local_cfg_dir for FHS /usr/local/etc (suggested by mst) - add XDG Base Directory Specification support (suggested by daxim) - update test for config_dirs - BinGOs test system users don't have a home directory 0.002 2010-07-27 - add here_cfg_dir 0.001 2010-07-26 - First version, released on an unsuspecting world. File-ConfigDir-0.017/lib/000755 000765 000024 00000000000 12517443325 014760 5ustar00snostaff000000 000000 File-ConfigDir-0.017/Makefile.PL000644 000765 000024 00000011407 12517416627 016174 0ustar00snostaff000000 000000 use strict; use warnings; use 5.008001; use ExtUtils::MakeMaker; my %RUN_DEPS = ( 'Carp' => 0, 'File::Basename' => 0, 'File::Path' => '2.00', 'File::Spec' => 0, 'FindBin' => 0, ); my %CONFIGURE_DEPS = ( 'ExtUtils::MakeMaker' => 0, ); my %BUILD_DEPS = (); my %TEST_DEPS = ( 'Test::More' => 0.90, ); WriteMakefile1( MIN_PERL_VERSION => '5.008001', META_ADD => { 'meta-spec' => { version => 2 }, resources => { homepage => 'https://metacpan.org/release/File-ConfigDir', repository => { url => 'https://github.com:perl5-utils/File-ConfigDir.git', web => 'https://github.com/perl5-utils/File-ConfigDir', type => 'git', }, bugtracker => { web => 'http://rt.cpan.org/Public/Dist/Display.html?Name=File-ConfigDir', mailto => 'bug-File-ConfigDir@rt.cpan.org', }, license => 'http://dev.perl.org/licenses/', x_IRC => "irc://irc.perl.org/#toolchain", x_MailingList => "mailto:cpan-workers\@perl.org'", }, prereqs => { develop => { requires => { 'Test::CPAN::Changes' => 0, 'Test::CheckManifest' => 0, 'Module::CPANTS::Analyse' => '0.96', 'Test::Kwalitee' => 0, 'Test::Pod' => 0, 'Test::Pod::Coverage' => 0, 'Test::Pod::Spelling::CommonMistakes' => 0, 'Test::Spelling' => 0, }, }, configure => { requires => {%CONFIGURE_DEPS}, }, build => { requires => {%BUILD_DEPS} }, test => { requires => {%TEST_DEPS} }, runtime => { recommends => { 'File::HomeDir' => '0.50', 'List::MoreUtils' => '0.22', }, requires => { %RUN_DEPS, perl => '5.8.1', }, }, }, }, NAME => 'File::ConfigDir', VERSION_FROM => 'lib/File/ConfigDir.pm', ABSTRACT_FROM => 'lib/File/ConfigDir.pm', LICENSE => 'perl', AUTHOR => q{Jens Rehsack }, CONFIGURE_REQUIRES => \%CONFIGURE_DEPS, PREREQ_PM => \%RUN_DEPS, BUILD_REQUIRES => \%BUILD_DEPS, TEST_REQUIRES => \%TEST_DEPS, test => { TESTS => 't/*.t xt/*.t' }, ); sub WriteMakefile1 { # originally written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. my %params = @_; my $eumm_version = $ExtUtils::MakeMaker::VERSION; $eumm_version = eval $eumm_version; die "EXTRA_META is deprecated" if ( exists( $params{EXTRA_META} ) ); die "License not specified" if ( !exists( $params{LICENSE} ) ); $params{TEST_REQUIRES} and $eumm_version < 6.6303 and $params{BUILD_REQUIRES} = { %{ $params{BUILD_REQUIRES} || {} }, %{ delete $params{TEST_REQUIRES} } }; #EUMM 6.5502 has problems with BUILD_REQUIRES $params{BUILD_REQUIRES} and $eumm_version < 6.5503 and $params{PREREQ_PM} = { %{ $params{PREREQ_PM} || {} }, %{ delete $params{BUILD_REQUIRES} } }; ref $params{AUTHOR} and "ARRAY" eq ref $params{AUTHOR} and $eumm_version < 6.5702 and $params{AUTHOR} = join( ", ", @{ $params{AUTHOR} } ); delete $params{CONFIGURE_REQUIRES} if ( $eumm_version < 6.52 ); delete $params{MIN_PERL_VERSION} if ( $eumm_version < 6.48 ); delete $params{META_MERGE} if ( $eumm_version < 6.46 ); delete $params{META_ADD}{prereqs} if ( $eumm_version < 6.58 ); delete $params{META_ADD}{'meta-spec'} if ( $eumm_version < 6.58 ); delete $params{META_ADD} if ( $eumm_version < 6.46 ); delete $params{LICENSE} if ( $eumm_version < 6.31 ); delete $params{AUTHOR} if ( $] < 5.005 ); delete $params{ABSTRACT_FROM} if ( $] < 5.005 ); delete $params{BINARY_LOCATION} if ( $] < 5.005 ); # more or less taken from Moose' Makefile.PL if ( $params{CONFLICTS} ) { my $ok = CheckConflicts(%params); exit(0) if ( $params{PREREQ_FATAL} and not $ok ); my $cpan_smoker = grep { $_ =~ m/(?:CR_SMOKER|CPAN_REPORTER|AUTOMATED_TESTING)/ } keys %ENV; unless ( $cpan_smoker || $ENV{PERL_MM_USE_DEFAULT} ) { sleep 4 unless ($ok); } delete $params{CONFLICTS}; } WriteMakefile(%params); } File-ConfigDir-0.017/MANIFEST000644 000765 000024 00000000432 12517443326 015343 0ustar00snostaff000000 000000 Changes lib/File/ConfigDir.pm Makefile.PL MANIFEST MANIFEST.SKIP README.md t/00-load.t t/01-simple.t t/02-plugg.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) File-ConfigDir-0.017/MANIFEST.SKIP000644 000765 000024 00000000466 12211360325 016103 0ustar00snostaff000000 000000 \B\.svn\b \B\.git\b \.gitignore$ \.[Bb][Aa][Kk]$ \.orig$ \.old$ \.tdy$ \.tmp$ \..*swp ^Makefile$ ^Build$ ^Build\.bat$ \.Inline/.* _Inline/.* \.bak$ \.tar$ \.tgz$ \.tar\.gz$ ^mess/ ^tmp/ ^testdata/ ^blib/ ^sandbox/ ^pm_to_blib$ ^_build/.* ~$ .*\.planner ^\..* File-ConfigDir-.* \bxt ^MYMETA\.json$ ^MYMETA\..*$ File-ConfigDir-0.017/META.json000644 000765 000024 00000004261 12517443326 015637 0ustar00snostaff000000 000000 { "abstract" : "Get directories of configuration files", "author" : [ "Jens Rehsack " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.150001", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "File-ConfigDir", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : {} }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Module::CPANTS::Analyse" : "0.96", "Test::CPAN::Changes" : "0", "Test::CheckManifest" : "0", "Test::Kwalitee" : "0", "Test::Pod" : "0", "Test::Pod::Coverage" : "0", "Test::Pod::Spelling::CommonMistakes" : "0", "Test::Spelling" : "0" } }, "runtime" : { "recommends" : { "File::HomeDir" : "0.50", "List::MoreUtils" : "0.22" }, "requires" : { "Carp" : "0", "File::Basename" : "0", "File::Path" : "2.00", "File::Spec" : "0", "FindBin" : "0", "perl" : "v5.8.1" } }, "test" : { "requires" : { "Test::More" : "0.9" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-File-ConfigDir@rt.cpan.org", "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=File-ConfigDir" }, "homepage" : "https://metacpan.org/release/File-ConfigDir", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "https://github.com:perl5-utils/File-ConfigDir.git", "web" : "https://github.com/perl5-utils/File-ConfigDir" }, "x_IRC" : "irc://irc.perl.org/#toolchain", "x_MailingList" : "mailto:cpan-workers@perl.org'" }, "version" : "0.017" } File-ConfigDir-0.017/META.yml000644 000765 000024 00000001730 12517443325 015464 0ustar00snostaff000000 000000 --- abstract: 'Get directories of configuration files' author: - 'Jens Rehsack ' build_requires: Test::More: '0.9' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.150001' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: File-ConfigDir no_index: directory: - t - inc recommends: File::HomeDir: '0.50' List::MoreUtils: '0.22' requires: Carp: '0' File::Basename: '0' File::Path: '2.00' File::Spec: '0' FindBin: '0' perl: v5.8.1 resources: IRC: irc://irc.perl.org/#toolchain MailingList: "mailto:cpan-workers@perl.org'" bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=File-ConfigDir homepage: https://metacpan.org/release/File-ConfigDir license: http://dev.perl.org/licenses/ repository: https://github.com:perl5-utils/File-ConfigDir.git version: '0.017' File-ConfigDir-0.017/README.md000644 000765 000024 00000002134 12465161267 015475 0ustar00snostaff000000 000000 ## Name File::ConfigDir ## Description This module is a helper for installing, reading and finding configuration file locations. It's intended to work in every supported Perl5 environment and will always try to Do The Right Thing(tm). ## Build/Installation cpan File::ConfigDir ## Copyright/License Copyright (C) 2010-2015 Jens Rehsack 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 for more information. ## Documentation/Support After installing, you can find documentation for this module with the perldoc command. perldoc File::ConfigDir You can also look for information at: RT, CPAN's request tracker http://rt.cpan.org/NoAuth/Bugs.html?Dist=File-ConfigDir AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/File-ConfigDir CPAN Ratings http://cpanratings.perl.org/d/File-ConfigDir Search CPAN http://search.cpan.org/dist/File-ConfigDir/ File-ConfigDir-0.017/t/000755 000765 000024 00000000000 12517443325 014455 5ustar00snostaff000000 000000 File-ConfigDir-0.017/t/00-load.t000644 000765 000024 00000000312 12236206147 015767 0ustar00snostaff000000 000000 #!perl -T use Test::More tests => 1; BEGIN { use_ok( 'File::ConfigDir' ) || BAIL_OUT "Couldn't load File::ConfigDir"; } diag( "Testing File::ConfigDir $File::ConfigDir::VERSION, Perl $], $^X" ); File-ConfigDir-0.017/t/01-simple.t000644 000765 000024 00000002470 12217064057 016352 0ustar00snostaff000000 000000 #!perl use strict; use warnings; eval { require local::lib; #local::lib->import(); }; use Test::More; use File::ConfigDir ':ALL'; my @supported_functions = ( qw(config_dirs system_cfg_dir desktop_cfg_dir), qw(core_cfg_dir site_cfg_dir vendor_cfg_dir), qw(local_cfg_dir here_cfg_dir singleapp_cfg_dir), qw(xdg_config_dirs xdg_config_home user_cfg_dir), ); foreach my $fn (@supported_functions) { my $faddr; ok( $faddr = File::ConfigDir->can($fn), "Can $fn" ); my @dirs = &{$faddr}(); note( "$fn: " . join( ",", @dirs ) ); if ( $fn =~ m/(?:xdg_)?config_dirs/ or $fn =~ m/(?:machine|desktop)_cfg_dir/ ) { ok( scalar @dirs >= 1, "config_dirs" ) or diag( join( ",", @dirs ) ); # we expect at least system_cfg_dir } elsif ( $fn =~ m/(?:local|user)_cfg_dir/ || $fn eq "xdg_config_home" ) { ok( scalar @dirs <= 1, $fn ) or diag( join( ",", @dirs ) ); # probably we do not have local::lib or File::HomeDir } elsif( $^O eq "MSWin32" and $fn eq "local_cfg_dir" ) { ok( scalar @dirs == 0, $fn ) or diag( join( ",", @dirs ) ); } else { ok( scalar @dirs == 1, $fn ) or diag( join( ",", @dirs ) ); } } done_testing(); File-ConfigDir-0.017/t/02-plugg.t000644 000765 000024 00000003714 12232467407 016205 0ustar00snostaff000000 000000 #!perl use strict; use warnings; use Carp qw(croak); use Test::More; use File::Basename; use File::Path; use File::Spec; use File::ConfigDir 'config_dirs'; my $test_dir; END { defined( $test_dir ) and rmtree $test_dir; } sub test_dir { unless( defined( $test_dir ) ) { $test_dir = File::Spec->rel2abs( File::Spec->curdir () ); $test_dir = File::Spec->catdir ( $test_dir, "test_output_" . $$ ); $^O eq 'VMS' and $test_dir = VMS::Filespec::unixify($test_dir); rmtree $test_dir; mkpath $test_dir; # create our two test dirs mkpath ( File::Spec->catdir( $test_dir, 'plugg', 'extra' ) ); mkpath ( File::Spec->catdir( $test_dir, 'pure' ) ); } return $test_dir; } test_dir(); my $plugg_src = sub { my @cfg_base = @_; return File::Spec->catdir( $test_dir, 'plugg', @cfg_base); }; my $pure_src = sub { my @cfg_base = @_; 0 == scalar(@cfg_base) or croak "pure_src(), not pure_src(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; return File::Spec->catdir( $test_dir, 'pure' ); }; ok(File::ConfigDir::_plug_dir_source($plugg_src), "registered extensible plugin"); ok(File::ConfigDir::_plug_dir_source($pure_src, "0E0"), "registered pure plugin"); ok(!File::ConfigDir::_plug_dir_source(), "registered nothing"); ok(!File::ConfigDir::_plug_dir_source(undef), "registered undef"); my @dirs = config_dirs(); note( "config_dirs: " . join( ",", @dirs ) ); ok( scalar @dirs >= 3, "config_dirs" ); # we expect system_cfg_dir + plugs is( $dirs[-1], File::Spec->catdir( $test_dir, 'pure'), 'pure'); is( $dirs[-2], File::Spec->catdir( $test_dir, 'plugg'), 'plugg'); @dirs = config_dirs(qw(extra)); note( "config_dirs: " . join( ",", @dirs ) ); ok( scalar @dirs >= 2, "config_dirs" ); # we expect our plugs is( $dirs[-1], File::Spec->catdir( $test_dir, 'pure'), 'pure with extra'); is( $dirs[-2], File::Spec->catdir( $test_dir, 'plugg', 'extra'), 'plugg with extra'); done_testing(); File-ConfigDir-0.017/lib/File/000755 000765 000024 00000000000 12517443325 015637 5ustar00snostaff000000 000000 File-ConfigDir-0.017/lib/File/ConfigDir.pm000644 000765 000024 00000034514 12517416775 020061 0ustar00snostaff000000 000000 package File::ConfigDir; use warnings; use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); use Carp qw(croak); use Config; use Cwd (); use Exporter (); use FindBin (); use File::Basename (); use File::Spec (); =head1 NAME File::ConfigDir - Get directories of configuration files =cut $VERSION = '0.017'; @ISA = qw(Exporter); @EXPORT = (); @EXPORT_OK = ( qw(config_dirs system_cfg_dir desktop_cfg_dir), qw(xdg_config_dirs machine_cfg_dir), qw(core_cfg_dir site_cfg_dir vendor_cfg_dir), qw(locallib_cfg_dir local_cfg_dir), qw(here_cfg_dir singleapp_cfg_dir), qw(xdg_config_home user_cfg_dir) ); %EXPORT_TAGS = ( ALL => [@EXPORT_OK], ); my $haveFileHomeDir = 0; eval { require File::HomeDir; $haveFileHomeDir = 1; }; eval "use List::MoreUtils qw/uniq/;"; __PACKAGE__->can("uniq") or eval <<'EOP'; # from PP part of List::MoreUtils sub uniq(&@) { my %h; map { $h{$_}++ == 0 ? $_ : () } @_; } EOP =head1 SYNOPSIS use File::ConfigDir ':ALL'; my @cfgdirs = config_dirs(); my @appcfgdirs = config_dirs('app'); # install support my $site_cfg_dir = (site_cfg_dir())[0]; my $vendor_cfg_dir = (site_cfg_dir()))[0]; =head1 DESCRIPTION This module is a helper for installing, reading and finding configuration file locations. It's intended to work in every supported Perl5 environment and will always try to Do The Right Thing(tm). C is a module to help out when perl modules (especially applications) need to read and store configuration files from more than one location. Writing user configuration is easy thanks to L, but what when the system administrator needs to place some global configuration or there will be system related configuration (in C on UNIX(tm) or C<$ENV{windir}> on Windows(tm)) and some network configuration in nfs mapped C or C<$ENV{ALLUSERSPROFILE} . "\\Application Data\\p5-app">, respectively. C has no "do what I mean" mode - it's entirely up to the user to pick the right directory for each particular application. =head1 EXPORT Every function listed below can be exported, either by name or using the tag C<:ALL>. =head1 SUBROUTINES/METHODS All functions can take one optional argument as application specific configuration directory. If given, it will be embedded at the right (tm) place of the resulting path. =cut sub _find_common_base_dir { my ( $dira, $dirb ) = @_; my ( $va, $da, undef ) = File::Spec->splitpath($dira); my ( $vb, $db, undef ) = File::Spec->splitpath($dirb); my @dirsa = File::Spec->splitdir($da); my @dirsb = File::Spec->splitdir($db); my @commondir; my $max = $#dirsa < $#dirsb ? $#dirsa : $#dirsb; for my $i ( 0 .. $max ) { $dirsa[$i] eq $dirsb[$i] or last; push( @commondir, $dirsa[$i] ); } File::Spec->catdir( $va, @commondir ); } =head2 system_cfg_dir Returns the configuration directory where configuration files of the operating system resides. For Unices this is C, for MSWin32 it's the value of the environment variable C<%windir%>. =cut my $system_cfg_dir = sub { my @cfg_base = @_; my @dirs = File::Spec->catdir( $^O eq "MSWin32" ? $ENV{windir} : "/etc", @cfg_base ); @dirs; }; sub system_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "system_cfg_dir(;\$), not system_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $system_cfg_dir->(@cfg_base); } =head2 machine_cfg_dir Alias for desktop_cfg_dir - deprecated. =head2 xdg_config_dirs Alias for desktop_cfg_dir =head2 desktop_cfg_dir Returns the configuration directory where configuration files of the desktop applications resides. For Unices this is C, for MSWin32 it's the value of the environment variable C<%ALLUSERSPROFILE%> concatenated with the basename of the environment variable C<%APPDATA%>. =cut my $desktop_cfg_dir = sub { my @cfg_base = @_; my @dirs; if ( $^O eq "MSWin32" ) { my $alluserprof = $ENV{ALLUSERSPROFILE}; my $appdatabase = File::Basename::basename( $ENV{APPDATA} ); @dirs = ( File::Spec->catdir( $alluserprof, $appdatabase, @cfg_base ) ); } else { if ( $ENV{XDG_CONFIG_DIRS} ) { @dirs = split( ":", $ENV{XDG_CONFIG_DIRS} ); @dirs = map { File::Spec->catdir( $_, @cfg_base ) } @dirs; } else { @dirs = ( File::Spec->catdir( "/etc", "xdg", @cfg_base ) ); } } @dirs; }; sub desktop_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "desktop_cfg_dir(;\$), not desktop_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $desktop_cfg_dir->(@cfg_base); } no warnings 'once'; *machine_cfg_dir = \&desktop_cfg_dir; *xdg_config_dirs = \&desktop_cfg_dir; use warnings; =head2 core_cfg_dir Returns the C directory below C<$Config{prefix}>. =cut my $core_cfg_dir = sub { my @cfg_base = @_; my @dirs = ( File::Spec->catdir( $Config{prefix}, "etc", @cfg_base ) ); @dirs; }; sub core_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "core_cfg_dir(;\$), not core_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $core_cfg_dir->(@cfg_base); } =head2 site_cfg_dir Returns the C directory below C<$Config{sitelib_stem}> or the common base directory of C<$Config{sitelib}> and C<$Config{sitebin}>. =cut my $site_cfg_dir = sub { my @cfg_base = @_; my @dirs; if ( $Config{sitelib_stem} ) { push( @dirs, File::Spec->catdir( $Config{sitelib_stem}, "etc", @cfg_base ) ); } else { my $sitelib_stem = _find_common_base_dir( $Config{sitelib}, $Config{sitebin} ); push( @dirs, File::Spec->catdir( $sitelib_stem, "etc", @cfg_base ) ); } @dirs; }; sub site_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "site_cfg_dir(;\$), not site_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $site_cfg_dir->(@cfg_base); } =head2 vendor_cfg_dir Returns the C directory below C<$Config{vendorlib_stem}> or the common base directory of C<$Config{vendorlib}> and C<$Config{vendorbin}>. =cut my $vendor_cfg_dir = sub { my @cfg_base = @_; my @dirs; if ( $Config{vendorlib_stem} ) { push( @dirs, File::Spec->catdir( $Config{vendorlib_stem}, "etc", @cfg_base ) ); } else { my $vendorlib_stem = _find_common_base_dir( $Config{vendorlib}, $Config{vendorbin} ); push( @dirs, File::Spec->catdir( $vendorlib_stem, "etc", @cfg_base ) ); } @dirs; }; sub vendor_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "vendor_cfg_dir(;\$), not vendor_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $vendor_cfg_dir->(@cfg_base); } =head2 singleapp_cfg_dir Returns the configuration file for standalone installed applications. In Unix speak, installing JRE to C<< /usr/local/jre- >> means there is a C<< /usr/local/jre-/bin/java >> and going from it's directory name one above and into C there is the I. For a Perl module it means, we're assuming that C<$FindBin::Bin> is installed as a standalone package somewhere, eg. into C - as recommended for pkgsrc ;) =cut my $singleapp_cfg_dir = sub { my @dirs = ( map { eval { Cwd::abs_path($_) } or File::Spec->canonpath($_) } File::Spec->catdir( $FindBin::RealDir, "..", "etc" ) ); @dirs; }; sub singleapp_cfg_dir { my @cfg_base = @_; 0 == scalar(@cfg_base) or croak "singleapp_cfg_dir(), not singleapp_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $singleapp_cfg_dir->(); } =head2 local_cfg_dir Returns the configuration directory for distribution independent, 3rd party applications. While this directory doesn't exists for MSWin32, there will be only the path C for Unices. =cut my $local_cfg_dir = sub { my @cfg_base = @_; my @dirs; unless ( $^O eq "MSWin32" ) { push( @dirs, File::Spec->catdir( "/usr", "local", "etc", @cfg_base ) ); } @dirs; }; sub local_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "local_cfg_dir(;\$), not local_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $local_cfg_dir->(@cfg_base); } =head2 locallib_cfg_dir Extracts the C from C<$ENV{PERL_MM_OPT}> and returns the C directory below it. =cut my $locallib_cfg_dir = sub { my @cfg_base = @_; my @dirs; if ( $INC{'local/lib.pm'} && $ENV{PERL_MM_OPT} && $ENV{PERL_MM_OPT} =~ m/.*INSTALL_BASE=([^"']*)['"]?$/ ) { ( my $cfgdir = $ENV{PERL_MM_OPT} ) =~ s/.*INSTALL_BASE=([^"']*)['"]?$/$1/; push( @dirs, File::Spec->catdir( $cfgdir, "etc", @cfg_base ) ); } @dirs; }; sub locallib_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "locallib_cfg_dir(;\$), not locallib_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $locallib_cfg_dir->(@cfg_base); } =head2 here_cfg_dir Returns the path for the C directory below the current working directory. =cut my $here_cfg_dir = sub { my @cfg_base = @_; my @dirs = ( File::Spec->catdir( File::Spec->rel2abs( File::Spec->curdir() ), @cfg_base, "etc" ) ); @dirs; }; sub here_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "here_cfg_dir(;\$), not here_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $here_cfg_dir->(@cfg_base); } =head2 user_cfg_dir Returns the users home folder using L. Without File::HomeDir, nothing is returned. =cut my $user_cfg_dir = sub { my @cfg_base = @_; my @dirs; $haveFileHomeDir and @dirs = ( File::Spec->catdir( File::HomeDir->my_home(), map { "." . $_ } @cfg_base ) ); @dirs; }; sub user_cfg_dir { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "user_cfg_dir(;\$), not user_cfg_dir(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $user_cfg_dir->(@cfg_base); } =head2 xdg_config_home Returns the user configuration directory for desktop applications. If C<< $ENV{XDG_CONFIG_HOME} >> is not set, for MSWin32 the value of C<< $ENV{APPDATA} >> is return and on Unices the C<.config> directory in the users home folder. Without L, on Unices the returned list might be empty. =cut my $xdg_config_home = sub { my @cfg_base = @_; my @dirs; if ( $ENV{XDG_CONFIG_HOME} ) { @dirs = split( ":", $ENV{XDG_CONFIG_HOME} ); @dirs = map { File::Spec->catdir( $_, @cfg_base ) } @dirs; } elsif ( $^O eq "MSWin32" ) { @dirs = ( File::Spec->catdir( $ENV{APPDATA}, @cfg_base ) ); } else { $haveFileHomeDir and @dirs = ( File::Spec->catdir( File::HomeDir->my_home(), ".config", @cfg_base ) ); } @dirs; }; sub xdg_config_home { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "xdg_config_home(;\$), not xdg_config_home(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; $xdg_config_home->(@cfg_base); } my ( @extensible_bases, @pure_bases ); push( @extensible_bases, $system_cfg_dir, $desktop_cfg_dir, $local_cfg_dir, $singleapp_cfg_dir, $core_cfg_dir, $site_cfg_dir, $vendor_cfg_dir, $here_cfg_dir, $user_cfg_dir, $xdg_config_home ); push( @pure_bases, 3 ); =head2 config_dirs @cfgdirs = config_dirs(); @cfgdirs = config_dirs( 'appname' ); Tries to get all available configuration directories as described above. Returns those who exists and are readable. =cut sub config_dirs { my @cfg_base = @_; 1 < scalar(@cfg_base) and croak "config_dirs(;\$), not config_dirs(" . join( ",", ("\$") x scalar(@cfg_base) ) . ")"; my @dirs = (); my $pure_idx = 0; foreach my $idx ( 0 .. $#extensible_bases ) { my $pure; $pure_idx <= $#pure_bases and $idx == $pure_bases[$pure_idx] and $pure = ++$pure_idx; push( @dirs, $extensible_bases[$idx]->( ( $pure ? () : @cfg_base ) ) ); } @dirs = grep { -d $_ && -r $_ } uniq(@dirs); @dirs; } =head2 _plug_dir_source my $dir_src = sub { return _better_config_dir(@_); } File::ConfigDir::_plug_dir_source($dir_src); my $pure_src = sub { return _better_config_plain_dir(@_); } File::ConfigDir::_plug_dir_source($pure_src, 1); # see 2nd arg is true Registers more sources to ask for suitable directories to check or search for config files. Each L will traverse them in subsequent invocations, too. Returns the number of directory sources in case of succes. Returns nothing when C<$dir_src> is not a code ref. =cut sub _plug_dir_source { my ( $dir_source, $pure ) = @_; $dir_source or return; "CODE" eq ref $dir_source or return; push( @extensible_bases, $dir_source ); $pure and push( @pure_bases, $#extensible_bases ); 1; } =head1 AUTHOR Jens Rehsack, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc File::ConfigDir You can also look for information at: =over 4 =item * RT: CPAN's request tracker L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS Thanks are sent out to Lars Dieckow (daxim) for his suggestion to add support for the Base Directory Specification of the Free Desktop Group. Matthew S. Trout (mst) earns the credit to suggest C and remind about C. =head1 LICENSE AND COPYRIGHT Copyright 2010-2015 Jens Rehsack. 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. =head1 SEE ALSO L, L, L (Unices only) =cut 1; # End of File::ConfigDir