#!/usr/local/bin/perl
###########################################
# config-patch 
# 2005, Mike Schilli <cpan@perlmeister.com>
###########################################
use strict;
use warnings;
use Getopt::Std;
use Pod::Usage;
use Config::Patch;

use vars qw($CVSVERSION);

$CVSVERSION = '$Revision: 1.7 $';

getopts("lapc:s:k:f:rhv", \my %opts);
pod2usage() if $opts{h};

if($opts{v}) {
    my ($version) = $CVSVERSION =~ /(\d\S+)/;
    die "$0 $version\n";
}

# Mandatory parameters
if(! exists $opts{k} or 
   ! exists $opts{f}) {
    pod2usage();
}

my $patcher = Config::Patch->new(file  => $opts{f}, key => $opts{k},
                                 flock => $opts{l});

if($opts{a}) {
    my $patch = join "", <>;
    $patcher->append($patch);
} elsif($opts{p}) {
    my $patch = join "", <>;
    $patcher->prepend($patch);
} elsif($opts{r}) {
    $patcher->remove($opts{k});
} elsif($opts{c}) {
    $patcher->comment_out(qr($opts{c}));
} elsif($opts{s}) {
    my $patch = join "", <>;
    $patcher->replace(qr($opts{s}), $patch);
}

__END__

=head1 NAME

    config-patch - Apply modifications to config files and take them back

=head1 SYNOPSIS

        # Append a patch
    echo "my patch text" | config-patch -a -k key -f config_file

        # Prepend a patch
    echo "my patch text" | config-patch -p -k key -f config_file

        # Remove a patch
    config-patch -r -k key -f config_file

        # Patch a section matched by a regex
    echo "replace" | config-patch -s 'regex' -k key -f config_file

        # Comment out a section matched by a regex
    config-patch -c 'regex' -k key -f config_file

=head1 OPTIONS

=over 8

=item B<-a>

Appends text to the configuration file. The text can be provided either
via STDIN or by specifying a file name:

            # Append a patch
    echo "my appended text" | config-patch -a -k key -f config_file

            # Append a patch
    config-patch -a -k key -f config_file appended_text.txt

=item B<-p>

Adds text to the beginning of a configuration file. The text can be
provided either via STDIN or by specifying a file name:

            # Prepend a patch
    echo "my prepend text" | config-patch -p -k key -f config_file

            # Prepend a patch
    config-patch -p -k key -f config_file prepended_text.txt

=item B<-r>

Removes the patch specified by the key (see C<-k>).

=item B<-f filename>

Specifies the config file to apply/remove the patch on/from.

=item B<-k key>

Specifies the key of the patch.

=item B<-l>

Flock the file exclusively before performing updates.

=item B<-h>

Prints this manual page in text format.

=item B<-s>

Apply a patch by using search-and-replace. The search term is a regular
expression, the replacement string 

    echo "none:" | config-patch -s 'all:.*' -k key -f config_file

=item B<-c>

Comment out a section in a configuration file matched by a regular expression.
Example:

    config-patch -c 'all:.*' -k key -f config_file

=item B<-v>

Prints the current version of C<config-patch>.

=back

=head1 DESCRIPTION

C<config-patch> performs modifications on configuration files and removes
them later. It keeps track of modifications by assigning a key to
each of them and by storing this key in a comment around the applied patch.

Then, when asked later to remove the patch, it will track it down the
patched section(s) by I<key> and remove them.

=head1 LEGALESE

Copyright 2005 by Mike Schilli, 
all rights reserved. This program is free 
software, you can redistribute it and/or
modify it under the same terms as Perl itself.

=head1 AUTHOR

2005, Mike Schilli <cpan@perlmeister.com>
