Skip to content

Commit

Permalink
Item12952: Refactor bootstrap, load, & save
Browse files Browse the repository at this point in the history
This fixes the issue that "discovered" extension "{Module}" entries are
not saved into the configuration.   The issue is that the Save process
clears and applies posted changes to the new configuration,  but values
quietly added to $Foswiki::cfg by the Configure::Pluggables:: are lost.

 - Eliminate the "NOT_SET" convention.  Bootstrap should really set
   everything that's needed, or die trying.
 - Refactor bootstrap out from Foswiki.pm into Configure::Load.  All
   methods of loading a configuration are in the same module now.  And
   the TestBootstrapPlugin will be able to drive the "real thing".
 - Unify save/restore of "BOOTSTRAP" variables, be they set during the
   actual bootstrap process, or by the "Pluggables" bootstrapping of
   newly installed extensions.   This simplifies the save code as well.

There is still a major bug related to extension discovery.
Configure::Pluggables::PLUGINS creates the {Plugins}{<plugin>}{Enabled}
but it does not merge in the Config.spec defaults for all the other plugin
settings.

I can't really fix it becuase I'm not sure if the original intention is
that the Config.spec be loaded in Pluggables::PLUGINS.   I suspect that
the jsonrpc  "getcfg" function should be called to load in all the
defaults. Currently only getspec is called to load the key definitions
and not their values.

This commit doesn't impact this either way.  Extensions installed before
the first run of Configure are configured correctly.  Extensions
installed after LocalSite.cfg exists don't get their default
configuration merged.
  • Loading branch information
gac410 committed Sep 13, 2014
1 parent 6149e44 commit 0d1b8f7
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 235 deletions.
196 changes: 1 addition & 195 deletions core/lib/Foswiki.pm
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ use warnings;
use Assert;
use Cwd qw( abs_path );
use Error qw( :try );
use File::Basename;
use File::Spec ();
use Monitor ();
use CGI (); # Always required to get html generation tags;
Expand Down Expand Up @@ -357,200 +356,7 @@ BEGIN {
$Foswiki::cfg{isVALID} = 1;
}
else {

use constant TRAUTO => 1;

# Failed to read LocalSite.cfg
# Clear out $Foswiki::cfg to allow variable expansion to work
# when reloading Foswiki.spec et al.
# SMELL: have to keep {Engine} as this is defined by the
# script (smells of a hack).
%Foswiki::cfg = ( Engine => $Foswiki::cfg{Engine} );

# Try to repair $Foswiki::cfg to a minimal configuration,
# using paths and URLs relative to this request. If URL
# rewriting is happening in the web server this is likely
# to go down in flames, but it gives us the best chance of
# recovering. We need to guess values for all the vars that
# would otherwise default to NOT SET.
eval "require FindBin";
die "Could not load FindBin to support configuration recovery: $@"
if $@;
FindBin::again(); # in case we are under mod_perl or similar
$FindBin::Bin =~ /^(.*)$/;
my $bin = $1;
$FindBin::Script =~ /^(.*)$/;
my $script = $1;
print STDERR
"AUTOCONFIG: Found Bin dir: $bin, Script name: $script using FindBin\n"
if (TRAUTO);

$Foswiki::cfg{ScriptSuffix} = ( fileparse( $script, qr/\.[^.]*/ ) )[2];
print STDERR
"AUTOCONFIG: Found SCRIPT SUFFIX $Foswiki::cfg{ScriptSuffix} \n"
if ( TRAUTO && $Foswiki::cfg{ScriptSuffix} );

my $protocol = $ENV{HTTPS} ? 'https' : 'http';
if ( $ENV{HTTP_HOST} ) {
$Foswiki::cfg{DefaultUrlHost} = "$protocol://$ENV{HTTP_HOST}";
print STDERR
"AUTOCONFIG: Set DefaultUrlHost $Foswiki::cfg{DefaultUrlHost} from HTTP_HOST $ENV{HTTP_HOST} \n"
if (TRAUTO);
}
elsif ( $ENV{SERVER_NAME} ) {
$Foswiki::cfg{DefaultUrlHost} = "$protocol://$ENV{SERVER_NAME}";
print STDERR
"AUTOCONFIG: Set DefaultUrlHost $Foswiki::cfg{DefaultUrlHost} from SERVER_NAME $ENV{SERVER_NAME} \n"
if (TRAUTO);
}
else {
# OK, so this is barfilicious. Think of something better.
$Foswiki::cfg{DefaultUrlHost} = "$protocol://localhost";
print STDERR
"AUTOCONFIG: barfilicious: Set DefaultUrlHost $Foswiki::cfg{DefaultUrlHost} \n"
if (TRAUTO);
}

# Examine the CGI path. The 'view' script it typically removed from the
# URL when using "Short URLs. If this BEGIN block is being run by
# 'view', then $Foswiki::cfg{ScriptUrlPaths}{view} will be correctly
# bootstrapped. If run for any other script, it will be set to a
# reasonable though probably incorrect default.
if ( $ENV{SCRIPT_NAME} ) {
print STDERR "AUTOCONFIG: Found SCRIPT $ENV{SCRIPT_NAME} \n"
if (TRAUTO);

if ( $ENV{SCRIPT_NAME} =~ m{^(.*?)/$script(\b|$)} ) {

# Conventional URLs with path and script
$Foswiki::cfg{ScriptUrlPath} = $1;
$Foswiki::cfg{ScriptUrlPaths}{view} =
$1 . '/view' . $Foswiki::cfg{ScriptSuffix};

# This might not work, depending on the websrver config,
# but it's the best we can do
$Foswiki::cfg{PubUrlPath} = "$1/../pub";
}
else {
# Short URLs but with a path
print STDERR
"AUTOCONFIG: Found path, but no script. short URLs \n"
if (TRAUTO);
$Foswiki::cfg{ScriptUrlPath} = $ENV{SCRIPT_NAME} . '/bin';
$Foswiki::cfg{ScriptUrlPaths}{view} = $ENV{SCRIPT_NAME};
$Foswiki::cfg{PubUrlPath} = $ENV{SCRIPT_NAME} . '/pub';
}
}
else {
# No script, no path, shortest URLs
print STDERR
"AUTOCONFIG: No path, No script, probably shorter URLs \n"
if (TRAUTO);
$Foswiki::cfg{ScriptUrlPaths}{view} = '';
$Foswiki::cfg{ScriptUrlPath} = '/bin';
$Foswiki::cfg{PubUrlPath} = '/pub';
}

print STDERR
"AUTOCONFIG: Using ScriptUrlPath $Foswiki::cfg{ScriptUrlPath} \n"
if (TRAUTO);
print STDERR "AUTOCONFIG: Using {ScriptUrlPaths}{view} "
. (
( defined $Foswiki::cfg{ScriptUrlPaths}{view} )
? $Foswiki::cfg{ScriptUrlPaths}{view}
: 'undef'
)
. "\n"
if (TRAUTO);
print STDERR
"AUTOCONFIG: Using PubUrlPath: $Foswiki::cfg{PubUrlPath} \n"
if (TRAUTO);

my %rel_to_root = (
DataDir => { dir => 'data', required => 0 },
LocalesDir => { dir => 'locale', required => 0 },
PubDir => { dir => 'pub', required => 0 },
ToolsDir => { dir => 'tools', required => 0 },
WorkingDir => {
dir => 'working',
required => 1,
validate_file => 'README'
},
TemplateDir => {
dir => 'templates',
required => 1,
validate_file => 'configure.tmpl'
},
ScriptDir => {
dir => 'bin',
required => 1,
validate_file => 'setlib.cfg'
}
);

# Note that we don't resolve x/../y to y, as this might
# confuse soft links
my $root = File::Spec->catdir( $bin, File::Spec->updir() );
$root =~ s{\\}{/}g;
my $fatal = '';
my $warn = '';
while ( my ( $key, $def ) = each %rel_to_root ) {
$Foswiki::cfg{$key} = File::Spec->rel2abs( $def->{dir}, $root );
$Foswiki::cfg{$key} = abs_path( $Foswiki::cfg{$key} );
( $Foswiki::cfg{$key} ) =
$Foswiki::cfg{$key} =~ m/^(.*)$/; # untaint

print STDERR "AUTOCONFIG: $key = $Foswiki::cfg{$key} \n"
if (TRAUTO);

if ( -d $Foswiki::cfg{$key} ) {
if ( $def->{validate_file}
&& !-e "$Foswiki::cfg{$key}/$def->{validate_file}" )
{
$fatal .=
"\n{$key} (guessed $Foswiki::cfg{$key}) $Foswiki::cfg{$key}/$def->{validate_file} not found";
}
}
elsif ( $def->{required} ) {
$fatal .= "\n{$key} (guessed $Foswiki::cfg{$key})";
}
else {
$warn .= "\n{$key} could not be guessed";
}
}
if ($fatal) {
die <<EPITAPH;
Unable to bootstrap configuration. LocalSite.cfg could not be loaded,
and Foswiki was unable to guess the locations of the following critical
directories: $fatal
EPITAPH
}

# Re-read Foswiki.spec *and Config.spec*. We need the Config.spec's
# to get a true picture of our defaults (notably those from
# JQueryPlugin. Without the Config.spec, no plugins get registered)
Foswiki::Configure::Load::readConfig( 0, 0, 1 );

_workOutOS();

$Foswiki::cfg{isVALID} = 1;
$Foswiki::cfg{isBOOTSTRAPPING} = 1;
eval 'require Foswiki::Plugins::ConfigurePlugin';
die
"LocalSite.cfg load failed, and ConfigurePlugin could not be loaded: $@"
if $@;

# Note: message is not I18N'd because there is no point; there
# is no localisation in a default cfg derived from Foswiki.spec
$system_message = <<BOOTS;
*WARNING !LocalSite.cfg could not be found, or failed to load.* %BR%This
Foswiki is running using a bootstrap configuration worked
out by detecting the layout of the installation. Any requests made to this
Foswiki will be treated as requests made by an administrator with full rights
to make changes! You should either:
* correct any permissions problems with an existing !LocalSite.cfg (see the webserver error logs for details), or
* visit [[%SCRIPTURL{configure}%?VIEWPATH=$Foswiki::cfg{ScriptUrlPaths}{view}][configure]] as soon as possible to generate a new one.
BOOTS
$system_message = Foswiki::Configure::Load::bootstrapConfig();
}

if ( $Foswiki::cfg{UseLocale} ) {
Expand Down
Loading

0 comments on commit 0d1b8f7

Please sign in to comment.