mvhub-dev team mailing list archive
-
mvhub-dev team
-
Mailing list archive
-
Message #00090
[Merge] lp:~omacneil/mvhub/improve_brave_add_dev_2010-04-16 into lp:mvhub
Dan MacNeil has proposed merging lp:~omacneil/mvhub/improve_brave_add_dev_2010-04-16 into lp:mvhub.
Requested reviews:
mvhub-dev (mvhub-dev)
streamlined the process of adding a developer setup to brave
fixed few couple bugs in mv_setup template merging code
--now it works if user config file is missing
--now it works if there is a key in template file that has an undefined value
--now it handles removing obselete keys from user config
removed some cruft
--
https://code.launchpad.net/~omacneil/mvhub/improve_brave_add_dev_2010-04-16/+merge/23633
Your team mvhub-dev is subscribed to branch lp:mvhub.
=== modified file 'app-mvhub/doc/checklists/setup_developer_on_brave.txt'
--- app-mvhub/doc/checklists/setup_developer_on_brave.txt 2010-03-08 08:07:29 +0000
+++ app-mvhub/doc/checklists/setup_developer_on_brave.txt 2010-04-18 21:00:31 +0000
@@ -22,7 +22,7 @@
__ do the bits that are automated (dir & db setup)
cdw
- mv_setup $NEW_DEV_USER
+ sudo app-mvhub/project-tools/bin/mv_setup $NEW_DEV_USER
___ Setup user's bazaar repository
@@ -84,7 +84,6 @@
sudo chown -R $NEW_DEV_USER:$NEW_DEV_USER \
/home/$NEW_DEV_USER/.bazaar
-
___ Create user's .ssh config file
@@ -99,76 +98,6 @@
# Set the permissions
sudo chown $NEW_DEV_USER:$NEW_DEV_USER /home/$NEW_DEV_USER/.ssh -R
-
- ___ Create user's muttrc file
-
- cdw
- cd app-mvhub/project-tools/developer_home_dir/
- sudo cp muttrc /home/$NEW_DEV_USER/.muttrc
-
- # Edit the muttrc file
- sudo $EDITOR /home/$NEW_DEV_USER/.muttrc
-
- # Change 'set pgp_sign_as="0x1234ABCD"' to be assigned to the
- # new user's pgp key. This is probably not setup at this point,
- # and will have to be revisited after the user creates their pgp
- # key. set the 'set from="$YOUR_EMAIL_ADDRESS" to be assigned to
- # the user's email address.
-
- # Set the permissions
-
- sudo chown $NEW_DEV_USER:$NEW_DEV_USER \
- /home/$NEW_DEV_USER/.muttrc
-
-___ copy conf templates
-
- cd $BASE_DIR
-
- sudo cp link-to-live-code/app-mvhub/project-tools/templates/template.conf $BASE_DIR/conf/nsp.conf
- sudo cp link-to-live-code/app-mvhub/project-tools/templates/template.conf $BASE_DIR/conf/mvh.conf
-
- sudo chown $NEW_DEV_USER.$NEW_DEV_USER $BASE_DIR/conf/ -R
- sudo chmod u=rw,g=rw,o= $BASE_DIR/conf -R
- sudo chmod u=rwx,g=rwxs,o= $BASE_DIR/conf
-
-
-___ edit mvh.conf
-
- cd $BASE_DIR/
-
- # replace any keys that start with BAD_
- # with ones that make sense
- sudo $EDITOR conf/mvh.conf
-
-
-[DATABASE]
- database_host=localhost
- database_name=$NEW_DEV_USER.mvh
- database_user=$NEW_DEV_USER
- # the database user's p---word
- database_magic_word=$DEV_USER_PASSWORD
-
-[NOTIFICATION]
-admin_email=$NEW_DEV_USER@xxxxxxxxxx
-dev_email=$NEW_DEV_USER@xxxxxxxxxx
-
-___ edit nsp.conf
-
- # replace any keys that start with BAD_
- # with ones that make sense
-sudo $EDITOR conf/nsp.conf
-
-[DATABASE]
- database_host=localhost
- database_name=$NEW_DEV_USER.nsp
- database_user=$NEW_DEV_USER
- # the database user's p---word
- database_magic_word=$DEV_USER_PASSWORD
-
-[NOTIFICATION]
-admin_email=$NEW_DEV_USER@xxxxxxxxxx
-dev_email=$NEW_DEV_USER@xxxxxxxxxx
-
___ setup apache basic auth
sudo htpasswd -cb $BASE_DIR/conf/auth_apache_users test test
=== modified file 'app-mvhub/project-tools/bin/mv_setup'
--- app-mvhub/project-tools/bin/mv_setup 2010-04-06 20:52:15 +0000
+++ app-mvhub/project-tools/bin/mv_setup 2010-04-18 21:00:31 +0000
@@ -2,117 +2,83 @@
# Purpose: automate setup / updaing of developer setup on brave
+# after modifiying test with:
+# sudo mv_setup $OTHER_USER_THAT_EXISTS
+# sudo mv_setup $NEW_USER
+# mv_setup
+
use strict;
use warnings;
+use English qw/-no_match_vars/;
+
use Carp;
use DBI;
use IO::Prompt;
use Config::Simple;
use MVHub::Utils::ConfigSimple;
+use MVHub::Utils::DB qw/get_dbh/;
-use English '-no_match_vars';
+my @WEBSITE_CODES = qw/ mvh nsp /;
{ # main
- local $OUTPUT_AUTOFLUSH=1;
-
+ local $OUTPUT_AUTOFLUSH = 1;
+
my $USERNAME = get_username_or_die();
- my $cfg = MVHub::Utils::ConfigSimple::create_config_from($ENV{MV_CONFIG_FILE});
- my @WEBSITE_CODES = qw/ mvh nsp /;
-
- my $base_dir = $cfg->param('BASE.dir');
-
- # should have nothing left on command line
- # at this point
- die usage() if scalar @ARGV;
+ die_if_bad_env_for($USERNAME);
+
+ my $cfg =
+ MVHub::Utils::ConfigSimple::create_config_from( $ENV{MV_CONFIG_FILE} );
system('clear');
-
- print "(re)making dirs in $base_dir$USERNAME...";
+
+ my $base_dir = $cfg->param('BASE.dir');
my @dirs = get_dirs_with( "$base_dir", $USERNAME );
make_dirs_from( $USERNAME, \@dirs );
- print "..done\n";
-
- my $prompt = "DESTROY and reload databases for $USERNAME (Y/N):";
- if ( IO::Prompt::prompt( $prompt, -YN ) ) {
-
- die "I refuse to destroy production database data"
- if $USERNAME =~ /www-data|production/;
-
- print "(re)making databases for $USERNAME this may take 50 seconds....\n";
- my $DBH = get_dbh();
-
- print "...done\n"
- if make_dbs_for( $DBH, $USERNAME, @WEBSITE_CODES );;
- }
- create_config_files_for($USERNAME, $cfg, @WEBSITE_CODES);
-}
-
-sub add_calculable_values{
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $username = shift or croak 'missing param: $username';
- my $site_code = shift or croak 'missing param: $site_code';
-
- $template_cfg->param('DATABASE.database_name',"$username.$site_code");
- $template_cfg->param('DATABASE.database_user',"$username");
- $template_cfg->param('NOTIFICATION.admin_email', "$username\@thecsl.org");
- $template_cfg->param('NOTIFICATION.dev_email', "$username\@thecsl.org");
- $template_cfg->param('SITE.website_name',"$site_code.$username.testing123.net");
- $template_cfg->param('SITE.website_code',"$site_code");
-
- return $template_cfg;
-}
-
-sub add_site_specific_values{
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $username = shift or croak 'missing param: $username';
- my %site_specific_values = %_;
-
- foreach my $key (keys %site_specific_values){
- $template_cfg->param($key, $site_specific_values{$key});
- }
- return $template_cfg;
-}
-
-sub add_user_generated_values{
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $user_cfg = shift or croak 'missing param: $user_cfg';
- my @keys = @_;
-
- foreach my $key (@keys){
- if (!($user_cfg->param($key))){
- prompt("Please enter a value for $key: ");
- $template_cfg->param($key,$_);
- }
- }
- return $template_cfg;
-}
-
-sub create_config_files_for{
- my $username = shift;
- my $cfg = shift;
- my @website_codes = @_;
- my @keys_for_user_generated_values = qw/ DATABASE.database_magic_word /;
-
- my $base_dir = $cfg->param('BASE.dir');
- my $template_cfg = new Config::Simple($cfg->param('ABSOLUTE_PATH.template_conf_dir') . "/template.conf");
-
- foreach my $site_code (@website_codes){
- my $user_cfg = new Config::Simple(syntax=>'ini');
- if (-e "$base_dir/$username/conf/$site_code.conf") {
- $user_cfg-> read("$base_dir/$username/conf/$site_code.conf");
- }
-
- print "Editing Config: $base_dir/$username/conf/$site_code.conf\n";
- my %site_specific_values = get_site_specific_values($site_code);
-
- $template_cfg = add_site_specific_values($template_cfg, $username, %site_specific_values);
- $template_cfg = add_calculable_values($template_cfg, $username, $site_code);
- $template_cfg = add_user_generated_values($template_cfg, $user_cfg, @keys_for_user_generated_values);
-
- merge_conf_objects($template_cfg, $user_cfg);
-
- $user_cfg->write("$base_dir/$username/conf/$site_code.conf");
- }
+
+ make_databases_for( $USERNAME, @WEBSITE_CODES );
+
+ make_config_files_for( $USERNAME, $cfg, @WEBSITE_CODES );
+}
+
+sub add_calculable_values {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $username = shift or croak 'missing param: $username';
+ my $site_code = shift or croak 'missing param: $site_code';
+
+ $template_cfg->param( 'DATABASE.database_name', "$username.$site_code" );
+ $template_cfg->param( 'DATABASE.database_user', "$username" );
+ $template_cfg->param( 'NOTIFICATION.admin_email', "$username\@thecsl.org" );
+ $template_cfg->param( 'NOTIFICATION.dev_email', "$username\@thecsl.org" );
+ $template_cfg->param( 'SITE.website_name',
+ "$site_code.$username.testing123.net" );
+ $template_cfg->param( 'SITE.website_code', "$site_code" );
+
+ return $template_cfg;
+}
+
+sub add_site_specific_values {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $username = shift or croak 'missing param: $username';
+ my %site_specific_values = %_;
+
+ foreach my $key ( keys %site_specific_values ) {
+ $template_cfg->param( $key, $site_specific_values{$key} );
+ }
+ return $template_cfg;
+}
+
+sub add_user_generated_values {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $user_cfg = shift or croak 'missing param: $user_cfg';
+ my @keys = @_;
+
+ foreach my $key (@keys) {
+ if ( !( $user_cfg->param($key) ) ) {
+ prompt("Please enter a value for $key: ");
+ $template_cfg->param( $key, $_ );
+ }
+ }
+ return $template_cfg;
}
sub db_exists {
@@ -164,11 +130,12 @@
rolname = ?
SQL
- my $role_rows_aref = $dbh->selectall_arrayref( $sql, {Slice =>{} }, ($username) );
+ my $role_rows_aref =
+ $dbh->selectall_arrayref( $sql, { Slice => {} }, ($username) );
my $result = $$role_rows_aref[0]{rolcreaterole}
&& $$role_rows_aref[0]{rolcreatedb};
- return $result ? 1 :0;
+ return $result ? 1 : 0;
}
sub db_user_has_superuser_role {
@@ -184,8 +151,9 @@
rolname = ?
SQL
- my $role_rows_aref = $dbh->selectall_arrayref( $sql, {Slice=>{}}, ($username) );
- return $$role_rows_aref[0]{rolsuper} ? 1:0;
+ my $role_rows_aref =
+ $dbh->selectall_arrayref( $sql, { Slice => {} }, ($username) );
+ return $$role_rows_aref[0]{rolsuper} ? 1 : 0;
}
sub do_or_die {
@@ -196,21 +164,6 @@
or die "$cmd failed ABORTING\n";
}
-# depends a lot on brave.thecsl.org enviroment
-sub get_dbh {
-
- my %attr = (
- 'PrintError' => 0,
- 'RaiseError' => 1,
- 'AutoCommit' => 1,
- 'ShowErrorStatement' => 1,
- );
- my $dbh = DBI->connect( 'dbi:Pg:dbname=template1', '', '', \%attr )
- or die "couldn't connect to database";
-
- return $dbh;
-}
-
sub get_dirs_with {
my $base_dir = shift or croak 'missing param: $base_dir';
my $username = shift or croak 'missing param: $username';
@@ -275,19 +228,56 @@
return @dirs;
}
-sub get_site_specific_values{
- my $site_code = shift or croak 'missing param: $site_code';
-
- my %hash_of_site_specific_values = (
- 'mvh' => {
- 'SITE.location' => '"Massachusetts Merrimack Valley"',
- 'SITE.website_description' => 'Merrimack Valley Hub',
- 'NOTIFICATION.team_name' => 'Merrimack Valley Hub Team'},
- 'nsp' => {
- 'SITE.location' => '"Massachusetts North Shore"',
- 'SITE.website_description' => 'North Shore Portal',
- 'NOTIFICATION.team_name' => 'North Shore Portal Team'});
- return %{$hash_of_site_specific_values{$site_code}};
+sub get_site_specific_values {
+ my $site_code = shift or croak 'missing param: $site_code';
+
+ my %hash_of_site_specific_values = (
+ 'mvh' => {
+ 'SITE.location' => '"Massachusetts Merrimack Valley"',
+ 'SITE.website_description' => 'Merrimack Valley Hub',
+ 'NOTIFICATION.team_name' => 'Merrimack Valley Hub Team'
+ },
+ 'nsp' => {
+ 'SITE.location' => '"Massachusetts North Shore"',
+ 'SITE.website_description' => 'North Shore Portal',
+ 'NOTIFICATION.team_name' => 'North Shore Portal Team'
+ }
+ );
+ return %{ $hash_of_site_specific_values{$site_code} };
+}
+
+sub die_if_bad_env_for {
+ my $username = shift or croak 'missing parameter $username\n';
+ my $msg = '';
+
+ foreach my $var (qw/PERL5LIB MV_CONFIG_FILE/) {
+ $msg .= "$var not set"
+ if !defined $ENV{$var};
+ }
+
+ my $xtra_msg = <<'HERE';
+ if running with sudo edit /etc/sudoers to include line:
+
+ Defaults env_keep+="PERL5LIB MV_CONFIG_FILE"
+
+ also be sure you ran:
+
+ cdw
+HERE
+
+ if ($msg) {
+ $msg .= $xtra_msg;
+ }
+
+ $msg .= "\nneed to run under sudo if you aren't $username\n"
+ if ( $username ne $ENV{USER} && $EFFECTIVE_USER_ID != 0 );
+
+ $msg .=
+"\ncan't run mv_setup for user root, did you forget a \$user param on command line?\n"
+ if $username eq 'root';
+
+ die $msg if $msg;
+ return 1;
}
sub get_username_or_die {
@@ -305,6 +295,10 @@
die "'$username' is not a valid username" . usage();
}
+ # should have nothing left on command line
+ # at this point
+ die usage() if scalar @ARGV;
+
return $username;
}
@@ -312,13 +306,12 @@
my $dbh = shift or croak 'missing param: $dbh';
my $username = shift or croak 'missing param: $username';
my $suffix = shift or croak 'missing param: $db_name';
-
- my $cfg =
- MVHub::Utils::ConfigSimple::create_config_from($ENV{MV_CONFIG_FILE});
-
- my $path_to_project_tools = $cfg->param('ABSOLUTE_PATH.project_tools_dir');
- my $db_password = $cfg->param('DATABASE.database_magic_word');
-
+
+ my $cfg =
+ MVHub::Utils::ConfigSimple::create_config_from( $ENV{MV_CONFIG_FILE} );
+
+ my $path_to_project_tools = $cfg->param('ABSOLUTE_PATH.project_tools_dir');
+ my $db_password = $cfg->param('DATABASE.database_magic_word');
my $cmd = "export PGPASSWORD=$db_password ";
$cmd .= "&& psql -h localhost -U $username -d $username.$suffix ";
@@ -329,22 +322,62 @@
}
+sub make_config_files_for {
+ my $username = shift;
+ my $cfg = shift;
+ my @website_codes = @_;
+ my @keys_for_user_generated_values = qw/ DATABASE.database_magic_word /;
+
+ my $base_dir = $cfg->param('BASE.dir');
+ my $template_config_file =
+ $cfg->param('ABSOLUTE_PATH.template_conf_dir') . "/template.conf";
+ my $template_cfg = new Config::Simple($template_config_file)
+ or die "failed to create config object from $template_config_file";
+
+ foreach my $site_code (@website_codes) {
+
+ my $cfg_file = "$base_dir/$username/conf/$site_code.conf";
+ my $user_cfg = new Config::Simple( syntax => 'ini' );
+ if ( !-e $cfg_file ) {
+ make_empty_config_file_named($cfg_file);
+ }
+ $user_cfg->read($cfg_file);
+
+ print "Editing Config: $cfg_file\n";
+ my %site_specific_values = get_site_specific_values($site_code);
+
+ $template_cfg = add_site_specific_values( $template_cfg, $username,
+ %site_specific_values );
+ $template_cfg =
+ add_calculable_values( $template_cfg, $username, $site_code );
+ $template_cfg = add_user_generated_values( $template_cfg, $user_cfg,
+ @keys_for_user_generated_values );
+
+ merge_conf_objects( $template_cfg, $user_cfg );
+
+ $user_cfg->write("$base_dir/$username/conf/$site_code.conf");
+ }
+}
+
sub make_dbs_for {
my $dbh = shift or croak 'missing param: $dbh';
my $username = shift or croak 'missing param: $username';
- my @website_codes = @_;
-
+ my @website_codes = @_;
+
my $sql;
-
- if ( !db_user_has_needed_roles( $dbh, $ENV{USER} ) ) {
- warn "\nSkipping db stuff $ENV{USER} lacks CREATEDB or CREATEROLE\n";
+ my $user_running_cmd =
+ defined $ENV{SUDO_USER} ? $ENV{SUDO_USER} : $ENV{USER};
+ if ( !db_user_has_needed_roles( $dbh, $user_running_cmd ) ) {
+ warn
+"\nSkipping db stuff $user_running_cmd lacks CREATEDB or CREATEROLE\n";
return;
}
- if ( ( $ENV{USER} ne $username )
- && !db_user_has_superuser_role($dbh,$ENV{USER}) ){
+ if ( ( $user_running_cmd ne $username )
+ && !db_user_has_superuser_role( $dbh, $user_running_cmd ) )
+ {
my $msg = qq/
- skipping db stuff $ENV{USER} can't drop table owned by $username
+ skipping db stuff $user_running_cmd can't drop table owned by $username
without role SUPERUSER
/;
warn $msg;
@@ -356,20 +389,52 @@
$dbh->do($sql);
}
- foreach my $suffix ( @website_codes ) {
+ foreach my $suffix (@website_codes) {
if ( db_exists( $dbh, "$username.$suffix" ) ) {
$sql = qq{DROP DATABASE "$username.${suffix}"};
$dbh->do($sql);
}
+
# kludge to avoid 'db being currently being accessed' errs
- sleep 1;
+ sleep 1;
$sql = qq{CREATE DATABASE "$username.${suffix}" OWNER $username};
$dbh->do($sql);
load_test_data_for( $dbh, $username, $suffix );
}
-return 1;
+ return 1;
+}
+
+sub make_empty_config_file_named {
+ my $filename = shift or croak 'missing Param $filename';
+
+ open my $out_fh, '>', $filename
+ or die "failed to open $filename for writing error:$!\n";
+ print $out_fh "#Config file\n [ignore]\n";
+ close $out_fh
+ or die "failed to close $filename error:$!\n";
+ return 1;
+}
+
+sub make_databases_for {
+ my $username = shift or croak 'missing parameter: $username';
+ my @website_codes = @_ or croak 'mssing parameter: @website_codes';
+
+ my $prompt = "DESTROY and reload databases for $username (Y/N):";
+ if ( IO::Prompt::prompt( $prompt, -YN ) ) {
+
+ die "I refuse to destroy production database data"
+ if $username =~ /www-data|production/;
+
+ print
+ "(re)making databases for $username this may take 50 seconds....\n";
+ my $DBH = MVHub::Utils::DB::get_dbh( $ENV{MV_CONFIG_FILE} );
+
+ print "...done\n"
+ if make_dbs_for( $DBH, $username, @website_codes );
+
+ }
}
sub make_dirs_from {
@@ -377,16 +442,6 @@
my $dir_hrefs_href = shift or croak 'missing param: $dir_hrefs_href';
my @dir_hrefs = @$dir_hrefs_href;
- my $sudo_cmd;
-
- # don't need sudo to modify in our own dir
- if ( $username eq $ENV{USER} ) {
- $sudo_cmd = '';
- }
- else {
- $sudo_cmd = 'sudo ';
- }
-
foreach my $dir_href (@dir_hrefs) {
my $mkdir_cmd = "mkdir -p $dir_href->{dir}";
my $chown_cmd =
@@ -402,23 +457,32 @@
"chown -R $dir_href->{owner}:$dir_href->{group} $dir_href->{dir}";
}
my $chmod_cmd = "chmod $dir_href->{permissions} $dir_href->{dir}";
- do_or_die("$sudo_cmd $mkdir_cmd");
- do_or_die("$sudo_cmd $chown_cmd");
- do_or_die("$sudo_cmd $chmod_cmd");
+ do_or_die($mkdir_cmd);
+ do_or_die($chown_cmd);
+ do_or_die($chmod_cmd);
}
}
-sub merge_conf_objects{
- my $template_cfg = shift or croak 'missing param: $template_cfg';
- my $user_cfg = shift or croak 'missing param: $user_cfg';
-
- foreach my $key ($template_cfg->param()){
-
- if (! ($user_cfg->param($key))){
- $user_cfg->param($key, $template_cfg->param($key));
- }
- }
- return $user_cfg;
+sub merge_conf_objects {
+ my $template_cfg = shift or croak 'missing param: $template_cfg';
+ my $user_cfg = shift or croak 'missing param: $user_cfg';
+
+ foreach my $key ( $template_cfg->param() ) {
+ if ( !( $user_cfg->param($key) ) ) {
+ my $value= $template_cfg->param($key);
+ $value=defined $value?$value:'BAD_MISSING';
+ $user_cfg->param( $key, $value);
+ }
+ }
+
+ #remove keys no longer used
+ foreach my $key ($user_cfg->param()){
+ if (! defined $template_cfg->param($key)){
+ $user_cfg->delete($key);
+ }
+ }
+
+ return $user_cfg;
}
sub usage {
=== modified file 'app-mvhub/project-tools/bin/mv_su_test'
--- app-mvhub/project-tools/bin/mv_su_test 2009-06-24 17:59:08 +0000
+++ app-mvhub/project-tools/bin/mv_su_test 2010-04-18 21:00:31 +0000
@@ -22,11 +22,8 @@
set_env_from(%env);
# run tests
- my $cmd = "mv_prove app-mvhub/t/ -r";
- ( system($cmd) == 0 ) or die "Failed: $cmd \n";
- $cmd = "mv_prove lib-mvhub/t/ -r";
- ( system($cmd) == 0 ) or die "Failed: $cmd \n";
-
+ my $cmd = "mv_prove app-mvhub/t/ lib-mvhub/t/ -r";
+ ( system($cmd) == 0 ) or die "Failed: $cmd \n";
} #main
sub die_on_bad {
=== modified file 'lib-mvhub/lib/MVHub/Utils/ConfigSimple.pm'
--- lib-mvhub/lib/MVHub/Utils/ConfigSimple.pm 2009-12-27 22:28:47 +0000
+++ lib-mvhub/lib/MVHub/Utils/ConfigSimple.pm 2010-04-18 21:00:31 +0000
@@ -45,12 +45,12 @@
my $base_dir = $cfg->param('BASE.dir')
or $error_msg
.= "param: 'BASE.dir' not found in config file: '$config_file'\n";
-
croak $error_msg if $error_msg;
+ my $user = defined $ENV{SUDO_USER} ? $ENV{SUDO_USER} : $ENV{USER};
foreach my $path_name ( keys %$relative_paths_href ) {
my $absolute_path
- = "$base_dir/$ENV{USER}/$$relative_paths_href{$path_name}";
+ = "$base_dir/$user/$$relative_paths_href{$path_name}";
$path_name =~ s|^RELATIVE_PATH\.||;
$cfg->param( "ABSOLUTE_PATH.$path_name", $absolute_path );
}
Follow ups