Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
#!C:/perl/bin/perl.exe # # Program: prod.pl # Date: 1/17/2001 # Author: Ovid # # Purpose: prod.pl is used to convert programs to a "productionized" v +ersion by commenting out # lines ending with "$lineTag" or between the "$startTag" and + "$endTag". Then, it's # written out to a destination directory. Default behavior is + to backup the destination # file. The original files will NOT be touched. Of course, t +he source and target # directories should not be the same, or the "productionized" + files will overwrite the # originals. # # If a $lineTag is placed at the end of a line, it will be co +mmented out when moved into # production. A $startTag and an $endTag are used to delimit +code that should be commented # out for production. Nested tags and imbalanced tags are not + allowed as intent can not # be determined. use strict; use warnings; use File::Copy; use File::Find; use File::Path; use File::Basename; use Getopt::Std; use Win32::File; # Major portability problem :( use Cwd qw/getcwd abs_path/; # Please note that these tag values have been hardcoded into the POD. + If these values # are altered, please update the POD at the end of this program. my $lineTag = quotemeta '#//'; my $startTag = quotemeta '#/*'; my $endTag = quotemeta '#*/'; # The following makes for a very inefficient regex, but this program # will not be run frequently. my $extensions = join '|', qw( cgi pl pm ); # Use this to avoid copying self my $thisProgram = basename( $0 ); # Current working directory my $cwd = getcwd(); # This hash stores command line options my %option; # Set up source and target directories my $sourceDir = '.'; my $targetDir = 'C:/WINNT/Profiles/cp/Desktop/target/realtarget'; validateEnvironment(); # Mirror the directory structure find ( \&mirrorDirectories, $sourceDir ); print "\n\n"; # Here's where the real work gets done. if ( $option{ a } ) { # Get (a)ll filenames recursively find ( \&process, $sourceDir ); } else { # We got here one of two ways: # 1. Option C, which populates @ARGV # 2. Files were specified on command line foreach my $file ( @ARGV ) { if ( -e $file and ! -d $file ) { # Only do it if it exists and is not a directory process( $file ); } } } sub validateEnvironment { # They didn't tell us what to do. Spank that puppy! if ( ! @ARGV ) { &usage; exit; } # Get the command line switches. See docs getopts( 'acd:DhHns:', \%option ); $sourceDir = $option{ s } if exists $option{ s }; $targetDir = $option{ d } if exists $option{ d }; $sourceDir =~ s!/$!!; # If they supplied a trailing /, strip it $targetDir =~ s!/$!!; unless ( -d $sourceDir ) { die "$sourceDir does not appear to be a valid directory"; } unless ( -d $targetDir ) { print "\n$targetDir does not appear to be a valid directory\n" + . "Do you wish to create this directory (mkdir will fail i +f higher level directories do not exist)? "; my $response = <STDIN>; if ( $response =~ /^[yY]/ ) { mkdir $targetDir or die "Cannot mkdir $targetDir: $!"; } else { print "\n-- Program terminating --\n"; exit; } } if ( sameDirectory( $sourceDir, $targetDir ) ) { die "Source and target directories must not be the same!"; } if ( @ARGV && ( exists $option{ a } or exists $option{ c } ) ) { print "\nYou appear to have specified files on the command + line, but have also\n" . "specified -a or -c. Since these options determine +the appropriate filenames\n" . "your intention is unclear and the program is exitin +g."; exit; } if ( exists $option{ h } or exists $option{ H } ) { # They've asked for help &usage; exit; } # (a)ll directories and (c)urrent directory conflict. if ( exists $option{ a } and exists $option{ c } ) { print "\nYou have specified both -a and -c options.\nPlease re +ad the usage and correct."; &usage; exit; } if ( $option{ D } ) { print "You have asked to delete $targetDir and all subdirector +ies.\n\n" . "Are you sure you wish to do this? "; my $answer = <STDIN>; rmtree( $targetDir ) if $answer =~ /^[yY]/; print "\nRe-creating $targetDir\n"; mkdir $targetDir or die "Cannot mkdir $targetDir: $!"; } # Get all filenames in (c)urrent directory, overwriting @ARGV if ( exists $option{ c } ) { opendir DIR, "." or die "Can't open current directory: $!"; @ARGV = readdir(DIR); closedir DIR; } } sub process { my $fileName = $_ || shift; $fileName =~ s/\0//g; # Strip out null bites to prevent security h +oles # Probably not a problem with this script, b +ut a # good practice nonetheless return if $fileName eq $thisProgram; my $pathName = $File::Find::name; # The following is a no-op with -a. Pathname does not affect the +logic. Instead, it # is used to generate more informative error messages. File::Find +does the chdir() for us. $pathName = defined $pathName ? $pathName : $fileName; # We only process cgi, pl, or pm files return if $fileName !~ /([\w]+\.(?:$extensions))$/i; print "Processing $pathName\n"; my ( $startLine, $endLine ); my ( $startCount, $endCount ) = ( 0, 0 ); open FILE, "<$fileName" or die "Can't open $fileName for reading: +$!"; my @lineOfCode = <FILE>; close FILE; for my $index ( 0 .. $#lineOfCode ) { # Line tag if ( $lineOfCode[ $index ] =~ /$lineTag\s*$/ ) { # Comment out the line of code $lineOfCode[ $index ] =~ s/^/#/; } # Start tag if ( $lineOfCode[ $index ] =~ m!^\s*$startTag! ) { if ( defined $startLine ) { # ERROR: we've already found a start tag! nestingError( "start", $startLine, $index, $pathName ) +; return; }; $startLine = $index; $startCount++; } # End tag if ( $lineOfCode[ $index ] =~ m!^\s*$endTag! ) { $endLine = $index; $endCount++; } if ( defined $startLine and defined $endLine ) { if ( $endLine - $startLine > 1 ) { # Comment out lines between start and end tags for my $cleanIndex ( $startLine + 1 .. $endLine - 1) { $lineOfCode[ $cleanIndex ] =~ s/^/#/; } } undef $startLine; undef $endLine; } } if ( $startCount != $endCount ) { print "\n-- $pathName skipped due to imbalanced tags.\n" . "-- You have $startCount start tags and $endCount end ta +gs in file $fileName.\n"; return; } saveModifiedFile( $fileName, \@lineOfCode ); } sub mirrorDirectories { my $targ_dir = $File::Find::dir; $targ_dir =~ s/^$sourceDir/$targetDir/; if ( ! -d $targ_dir ) { print "Creating $targ_dir\n"; mkdir $targ_dir or die "Cannot mkdir $targ_dir: $!"; } } sub saveModifiedFile { my $fileName = shift; my @contents = @{ $_[0] }; my $contents = join '', @contents; my $relativePath = $File::Find::dir; $relativePath =~ s/^\.//; # remove preceeding dot my $fullPath = $targetDir . $relativePath . "/$fileName"; my $backUpFile = $fullPath . ".bak"; # Backing up the files is the default. If the specify the -n opti +on on # the command line, no backup of the files will occur. unless ( exists $option{ n } ) { print "\tBacking up $fileName to $backUpFile\n"; if ( -e $fullPath ) { unlink $backUpFile if -e $backUpFile; if ( ! copy ( $fullPath, "$backUpFile" ) ) { print "\tCouldn't copy $fileName to $backUpFile\n\tFil +e Skipped.\n"; return; } } } if ( -e $fullPath ) { Win32::File::SetAttributes( $fullPath, NORMAL ) or die "Can't +set $fileName to NORMAL: $!"; } open FILE, ">$fullPath" or die "Can't open $fullPath for writing: +$!"; print FILE $contents; close FILE; Win32::File::SetAttributes( $fullPath, READONLY ) or die "Can't se +t $fileName to READONLY: $!"; } sub sameDirectory { my ( $dir1, $dir2 ) = @_; # abs_path returns the absolute path of the directory or false, if + no such # path is available. -d $dir1 and $dir1 = abs_path( $dir1 ) or return -1; -d $dir2 and $dir2 = abs_path( $dir2 ) or return -1; $dir1 eq $dir2 ? 1 : 0 ; } sub nestingError { my ( $tag, $first, $last, $fileName ) = @_; $first++; $last++; print <<" END_HERE"; -- Mis-nested $tag tags found on lines $first and $last in $fileName. -- Please correct and rerun. -- $fileName skipped. END_HERE } sub usage { print <<" END_HERE"; USAGE: prod.pl file1.pl file2.cgi The above line will "productionize" file1.pl and file2.cgi if they + exist. The "productionized" files will be copied to the destination direc +tory. The following switches are available and may be combined: a - productionize (a)ll files recursively, starting with (s)ource +directory c - productionize all files in (c)urrent directory d - (d)estination directory D - recursive (D)elete of all files in destination. Will prompt f +or confirmation h - This message and exit. No processing will occur. H - Same as -h n - (n)o backup of files s - (s)ource directory NOTE: both -d and -s require an argument. Every switch is optional, but + at least one switch must be supplied. EXAMPLE: prod.pl -an -s C:/WINNT/Profiles/cp/desktop/somedir -d C:/WINNT/Pr +ofiles/cp/desktop/anotherdir/production The above command will recursively copy all files and folders from + the specified source to the destination directory with no backup of files. END_HERE } __END__ =head1 NAME prod.pl - Prep files for production =head1 SYNOPSIS C<prod.pl -a -s . -d C:/WINNT/profiles/cp/desktop/target> The above line will I<productionize> all files in source directory, re +cursively going through subdirectories. The I<productionized> files will be cop +ied to the destination directory in an identical folder structure. =head1 DESCRIPTION prod.pl allows programs to be developed in a testing environment witho +ut worrying about I<development only> features being copied into production. To u +se this, several tags have been identified. As of this writing, they are: =over 4 =item 1 C<#//> This is a B<line tag>. Append this to the end of a lin +e with nothing but whitespace following and prod.pl will comment out this line. =item 2 C<#/*> This is a B<start tag>. All lines I<between> start and + end tags will be commented out. =item 3 C<#*/> This is the aforementioned B<end tag>. =back The B<start tag> and B<end tag> must each be the I<first> item on thei +r respective lines. White space before these lines is permitted. These tags are useful for ensuring that C<use warnings;> or C<use CGI: +:Carp qw(fatalsToBrowser);> are not included in production code. Also, large sections of debuggin +g code (such as print statements) can be commented out by wrapping them in start and end tag +s. =head1 COMMAND LINE SWITCHES There are a variety of switches that may be used on the command line. + Generally, these switches may be combined, but common sense should be applied. Don't u +se C<-a> and C<-c> together, for example. The program will halt and tell you what a moro +n you are. The following switches are available (in alphabetical order) =over 4 =item 1 C<-a> This switch is used to I<productionize> all files in the + source directory and all subdirectories of the source directory. May not be used with +C<-c>. =item 2 C<-c> This switch is used to I<productionize> all files in the + current directory. No subdirectories will be used. =item 3 C<-d> This specifies the destination directory. This must not + be the same as the source directory. Requires an argument. =item 4 C<-D> This will erase all files and folders in the destination + directory. It will prompt you before continuing as this is unrecoverable. Use with B<ext +reme caution>. =item 5 C<-h> Help. This will generate a short synopsis of program us +age. =item 6 C<-H> Same as C<-h>. =item 7 C<-n> No backup. Typically, files to be overwritten in backup + directory are backed up by copying them to an identically named file with a I<.bak> extensi +on. This switch suppresses that backup. =item 8 C<-s> This specifies the source directory. This must not be t +he same as the destination directory. Requires an argument. =back =head1 AUTHOR Curtis A. Poe <poec@yahoo.com> =head1 MISCELLANEOUS This script uses the C<Win32::File> module and is not portable as a re +sult. This program will not copy or productionize itself. The program will die if source and target directories are the same. T +his is deliberate to prevent overwriting of source files. Mis-nested or imbalanced (e.g. three start tags and two end tags) tags + will cause a file to be skipped. All switches are optional, but I<something> must be used as an argumen +t. If the switches are excluded, prod.pl expects a list of files on the command line. Destination directory must exists prior to running the program. =cut

In reply to Auto prepare code for production by Ovid

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others musing on the Monastery: (6)
    As of 2015-07-05 21:43 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









      Results (68 votes), past polls