From 4d1167ffd72c77748a22a8dc1646a0d944be1441 Mon Sep 17 00:00:00 2001 From: Charles LeDoux Date: Fri, 1 Jul 2016 20:07:28 -0500 Subject: [PATCH] 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. --- Build.PL | 1 + META.json | 1 + META.yml | 1 + bin/stow.in | 38 +++++++++++++++++++++++++------------- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Build.PL b/Build.PL index a14b93b..3f63c0c 100644 --- a/Build.PL +++ b/Build.PL @@ -45,6 +45,7 @@ my $build = Module::Build->new( 'perl' => '5.006', 'Carp' => 0, 'IO::File' => 0, + 'Hash::Merge' => 0, }, script_files => [ 'bin/stow', 'bin/chkstow' ], all_from => 'lib/Stow.pm.in', diff --git a/META.json b/META.json index 2a455a4..dd806c9 100644 --- a/META.json +++ b/META.json @@ -17,6 +17,7 @@ "build" : { "requires" : { "IO::Scalar" : "0", + "Hash::Merge": "0", "Test::More" : "0", "Test::Output" : "0" } diff --git a/META.yml b/META.yml index f94d472..9bcbadb 100644 --- a/META.yml +++ b/META.yml @@ -4,6 +4,7 @@ author: - unknown build_requires: IO::Scalar: '0' + Hash::Merge: '0' Test::More: '0' Test::Output: '0' configure_requires: diff --git a/bin/stow.in b/bin/stow.in index fb42dbf..d056cec 100755 --- a/bin/stow.in +++ b/bin/stow.in @@ -438,6 +438,8 @@ use Getopt::Long qw(GetOptionsFromArray); use Stow; use Stow::Util qw(parent error); +use Hash::Merge qw( merge ); + my $ProgramName = $0; $ProgramName =~ s{.*/}{}; @@ -488,17 +490,29 @@ sub main { # Comments : checks @ARGV for valid package names #============================================================================ sub process_options { - - unshift @ARGV, get_config_file_options(); - #$,="\n"; print @ARGV,"\n"; # for debugging rc file - - my ($options, + # Get cli options. + my ($cli_options, $pkgs_to_unstow, $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); check_packages($pkgs_to_unstow, $pkgs_to_stow); + # Return merged and processed options. return ($options, $pkgs_to_unstow, $pkgs_to_stow); } @@ -611,16 +625,14 @@ sub check_packages { } } - #===== SUBROUTINE ============================================================ # Name : get_config_file_options() # Purpose : search for default settings in any .stowrc files # Parameters: none -# Returns : a list of default options -# Throws : no exceptions -# Comments : prepends the contents of '~/.stowrc' and '.stowrc' to the command -# : line so they get parsed just like normal arguments. (This was -# : hacked in so that Emil and I could set different preferences). +# Returns : (\%rc_options, \@rc_pkgs_to_unstow, \@rc_pkgs_to_stow) +# Throws : a fatal error if a bad option is given +# Comments : Parses the contents of '~/.stowrc' and '.stowrc' with the same +# parser as the command line options. #============================================================================= sub get_config_file_options { my @defaults = (); @@ -635,7 +647,7 @@ sub get_config_file_options { close $FILE or die "Could not close open file: $file\n"; } } - return @defaults; + return parse_options(@defaults); } #===== SUBROUTINE =========================================================== @@ -650,7 +662,7 @@ sub usage { my ($msg) = @_; if ($msg) { - print "$ProgramName: $msg\n\n"; + warn "$ProgramName: $msg\n\n"; } print <<"EOT";