2 # *** NOTE *** LEAVE THIS MODULE LIST AS A PARAGRAPH
6 our $VERSION = '0.0.3';
7 use English
qw( -no_match_vars );
8 use Fatal
qw( close chdir opendir closedir );
9 use File
::Temp
qw( tempdir );
10 use File
::Path
qw( mkpath );
11 use File
::Spec
::Functions
qw( file_name_is_absolute catfile );
12 use File
::Basename
qw( dirname );
13 use POSIX
qw( strftime );
14 use Getopt
::Long
qw( :config gnu_getopt );
16 # *** NOTE *** LEAVE EMPTY LINE ABOVE
19 my %default_config = ( # default values
20 workdir
=> '/tmp/our-deploy',
25 \
%config, 'usage|help|man',
26 'version', 'cleanup|c!',
27 'dryrun|dry-run', 'no-deploy!',
28 'show|show-options|s!', 'workdir|work-directory|deploy-directory|w=s',
29 'no-tempdir!', 'bundle|all-exec|X!',
30 'inspect|i=s', 'filelist!',
34 usage
() if $config{usage
};
35 version
() if $config{version
};
40 while (read DATA
, my $buffer, 4096) {
41 print {*STDOUT
} $buffer;
46 my $tar = Archive
::Tar
->new();
49 if ($config{filelist
}) {
51 print for $tar->list_files();
55 my %script_config = (%default_config, get_config
($tar));
58 print {*STDOUT
} Data
::Dumper
::Dumper
(\
%script_config);
62 # Merge configurations and go on
63 %config = (%script_config, %config);
65 if ($config{inspect
}) {
67 $config{'no-deploy'} = 1;
68 $config{'no-tempdir'} = 1;
69 $config{workdir
} = $config{inspect
};
72 if ($config{dryrun
}) {
74 print {*STDOUT
} Data
::Dumper
::Dumper
(\
%config);
78 # go into the working directory, creating any intermediate if needed
79 mkpath
($config{workdir
});
80 chdir($config{workdir
});
81 print {*STDERR
} "### Got into working directory '$config{workdir}'\n\n";
84 if (!$config{'no-tempdir'}) { # Only if not prohibited
85 my $now = strftime
('%Y-%m-%d_%H-%M-%S', localtime);
87 tempdir
($now . 'X' x
10, DIR
=> '.', CLEANUP
=> $config{cleanup
});
91 "### Created and got into temporary directory '$tempdir'\n";
92 print {*STDERR
} "### (will clean it up later)\n" if $config{cleanup
};
94 } ## end if (!$config{'no-tempdir'...
96 eval { # Not really needed, but you know...
97 $ENV{PATH
} = '/bin:/usr/bin:/sbin:/usr/sbin';
99 execute_deploy_programs
() unless $config{'no-deploy'};
101 carp
$EVAL_ERROR if $EVAL_ERROR;
103 # Get back so that cleanup can successfully happen, if requested
104 chdir '..' if defined $tempdir;
106 sub execute_deploy_programs
{
107 my @deploy_programs = @
{$config{deploy
} || []};
109 if ($config{bundle
}) { # add all executable scripts in current directory
110 print {*STDERR
} "### Auto-deploying all executables in main dir\n\n";
111 my %flag_for = map { $_ => 1 } @deploy_programs;
113 for my $item (sort readdir $dh) {
114 next if $flag_for{$item};
115 next unless ((-f
$item) || (-l
$item)) && (-x
$item);
116 $flag_for{$item} = 1;
117 push @deploy_programs, $item;
118 } ## end while (my $item = readdir...
120 } ## end if ($config{bundle})
123 for my $deploy (@deploy_programs) {
124 $deploy = catfile
('.', $deploy)
125 unless file_name_is_absolute
($deploy);
127 print {*STDERR
} "### Skipping '$deploy', not executable\n\n";
130 print {*STDERR
} "### Executing '$deploy'...\n";
131 system {$deploy} $deploy;
132 print {*STDERR
} "\n";
133 } ## end for my $deploy (@deploy_programs)
136 } ## end sub execute_deploy_programs
141 my ($file) = $tar->get_files('deployable/config.pl');
142 return unless $file && $file->has_content();
144 my $config = eval 'my ' . $file->get_content() or return;
145 return $config unless wantarray;
147 } ## end sub get_config
152 for my $file ($tar->get_files()) {
153 my ($area, $full_path) = split /\//mxs
, $file->full_path(), 2;
154 next unless $area eq 'root' || $area eq 'here';
156 my $dirprefix = $area eq 'here' ?
'.'
157 : $config{inspect
} ?
$area : '';
158 my $real_path = join('/', $dirprefix, $full_path);
160 print {*STDERR
} "### Extracting $full_path in '$area' => $real_path\n";
161 if ($file->is_dir()) {
165 mkpath
(dirname
$real_path);
166 write_file
($real_path, $file->get_content());
169 chmod $file->mode(), $real_path;
173 } ## end sub save_files
176 my $filename = shift;
177 open my $fh, '>', $filename or croak
"open('$filename'): $OS_ERROR";
185 print {*STDOUT
} <<"END_OF_USAGE" ;
188 More or less, this script is intended to be launched without parameters.
189 Anyway, you can also set the following options, which will override any
190 present configuration (except in "--show-options"):
192 * --usage | --man | --help
193 print these help lines and exit
196 print script version and exit
198 * --bundle | --all-exec | -X
199 treat all executables in the main deployment directory as scripts
202 * --cleanup | --no-cleanup
203 perform / don't perform temporary directory cleanup after work done
205 * --dryrun | --dry-run
206 print final options and exit
209 print a list of files that are shipped in the deploy script
211 * --inspect <dirname>
212 just extract all the stuff into <dirname> for inspection. Implies
213 --no-deploy, --no-tempdir, ignores --bundle (as a consequence of
214 --no-deploy), disables --cleanup and sets the working directory
218 prevent execution of deploy scripts (they are executed by default)
221 execute directly in workdir (see below), without creating the
224 * --show-options | -s
225 print configured options and exit
228 print out the tar file that contains all the shipped files
231 working base directory (a temporary subdirectory will be created
239 print "$0 version $VERSION\n";