Parse cli and stowrc files separately

Why:

* We want to selectively apply expansion to:
    * Only options from stowrc files.
    * Only options that take a path.
* This requires ability to:
    * Differentiate cli options from stowrc options
    * Distinguish between individual stowrc options.

This change addresses the need by:

* Options from ARGV and stowrc files are separately parsed, resulting in
  two options hashes.
    * Creating an option hash from stowrc files allows modification of
      specific arguments without having to rely on something like regex
      parsing of the options.

* get_config_file_options modified to return options hash.
    * Uses the same parse_options function that parses ARGV

* Add Hash:Merge to dependencies in order to merge the two option
  hashes.

* process_options() merges the two option hashes.
    * Get option hash for ARGV
    * Get option hash from get_config_file_options().
    * Merge the two hashes with Hash::Merge.
    * Sanitation and checks are ran on the merged options.

* The options -S, -D, and -R are ignored in stowrc files.
    * Due to the way argument parsing happens, the effect of these
      actions is not carried from stowrc into parsing of cli options.
    * It doesn't seem to make sense to put these options in stowrc
      anyway.
This commit is contained in:
Charles LeDoux 2016-07-01 20:07:28 -05:00 committed by Adam Spiers
parent feb885fda6
commit 4d1167ffd7
4 changed files with 28 additions and 13 deletions

View file

@ -45,6 +45,7 @@ my $build = Module::Build->new(
'perl' => '5.006', 'perl' => '5.006',
'Carp' => 0, 'Carp' => 0,
'IO::File' => 0, 'IO::File' => 0,
'Hash::Merge' => 0,
}, },
script_files => [ 'bin/stow', 'bin/chkstow' ], script_files => [ 'bin/stow', 'bin/chkstow' ],
all_from => 'lib/Stow.pm.in', all_from => 'lib/Stow.pm.in',

View file

@ -17,6 +17,7 @@
"build" : { "build" : {
"requires" : { "requires" : {
"IO::Scalar" : "0", "IO::Scalar" : "0",
"Hash::Merge": "0",
"Test::More" : "0", "Test::More" : "0",
"Test::Output" : "0" "Test::Output" : "0"
} }

View file

@ -4,6 +4,7 @@ author:
- unknown - unknown
build_requires: build_requires:
IO::Scalar: '0' IO::Scalar: '0'
Hash::Merge: '0'
Test::More: '0' Test::More: '0'
Test::Output: '0' Test::Output: '0'
configure_requires: configure_requires:

View file

@ -438,6 +438,8 @@ use Getopt::Long qw(GetOptionsFromArray);
use Stow; use Stow;
use Stow::Util qw(parent error); use Stow::Util qw(parent error);
use Hash::Merge qw( merge );
my $ProgramName = $0; my $ProgramName = $0;
$ProgramName =~ s{.*/}{}; $ProgramName =~ s{.*/}{};
@ -488,17 +490,29 @@ sub main {
# Comments : checks @ARGV for valid package names # Comments : checks @ARGV for valid package names
#============================================================================ #============================================================================
sub process_options { sub process_options {
# Get cli options.
unshift @ARGV, get_config_file_options(); my ($cli_options,
#$,="\n"; print @ARGV,"\n"; # for debugging rc file
my ($options,
$pkgs_to_unstow, $pkgs_to_unstow,
$pkgs_to_stow) = parse_options(@ARGV); $pkgs_to_stow) = parse_options(@ARGV);
# Get the .stowrc options.
# Note that rc_pkgs_to_unstow and rc_pkgs_to_stow are ignored.
my ($rc_options,
$rc_pkgs_to_unstow,
$rc_pkgs_to_stow) = get_config_file_options();
# Merge .stowrc and command line options.
# Preference is given to cli options.
# rc options come first in merged arrays.
# cli options overwrite conflicting rc options.
Hash::Merge::set_behavior('RIGHT_PRECEDENT');
my $options = merge($rc_options, $cli_options);
# Run checks on the merged options.
sanitize_path_options($options); sanitize_path_options($options);
check_packages($pkgs_to_unstow, $pkgs_to_stow); check_packages($pkgs_to_unstow, $pkgs_to_stow);
# Return merged and processed options.
return ($options, $pkgs_to_unstow, $pkgs_to_stow); return ($options, $pkgs_to_unstow, $pkgs_to_stow);
} }
@ -611,16 +625,14 @@ sub check_packages {
} }
} }
#===== SUBROUTINE ============================================================ #===== SUBROUTINE ============================================================
# Name : get_config_file_options() # Name : get_config_file_options()
# Purpose : search for default settings in any .stowrc files # Purpose : search for default settings in any .stowrc files
# Parameters: none # Parameters: none
# Returns : a list of default options # Returns : (\%rc_options, \@rc_pkgs_to_unstow, \@rc_pkgs_to_stow)
# Throws : no exceptions # Throws : a fatal error if a bad option is given
# Comments : prepends the contents of '~/.stowrc' and '.stowrc' to the command # Comments : Parses the contents of '~/.stowrc' and '.stowrc' with the same
# : line so they get parsed just like normal arguments. (This was # parser as the command line options.
# : hacked in so that Emil and I could set different preferences).
#============================================================================= #=============================================================================
sub get_config_file_options { sub get_config_file_options {
my @defaults = (); my @defaults = ();
@ -635,7 +647,7 @@ sub get_config_file_options {
close $FILE or die "Could not close open file: $file\n"; close $FILE or die "Could not close open file: $file\n";
} }
} }
return @defaults; return parse_options(@defaults);
} }
#===== SUBROUTINE =========================================================== #===== SUBROUTINE ===========================================================
@ -650,7 +662,7 @@ sub usage {
my ($msg) = @_; my ($msg) = @_;
if ($msg) { if ($msg) {
print "$ProgramName: $msg\n\n"; warn "$ProgramName: $msg\n\n";
} }
print <<"EOT"; print <<"EOT";