######################################################################
    Config::Patch 0.07
######################################################################

NAME
    Config::Patch - Patch configuration files and unpatch them later

SYNOPSIS
        use Config::Patch;

        my $patcher = Config::Patch->new( 
            file => "/etc/syslog.conf",
            key  => "mypatch", 
        );

            # Append a patch:
        $patcher->append(q{
            # Log my stuff
            my.*         /var/log/my
        });

            # Appends the following to /etc/syslog.conf:
            *-------------------------------------------
            | ...
            | #(Config::Patch-mypatch-append)
            | # Log my stuff
            | my.*         /var/log/my
            | #(Config::Patch-mypatch-append)
            *-------------------------------------------

            # Prepend a patch:
        $patcher->prepend(q{
            # Log my stuff
            my.*         /var/log/my
        });

            # Prepends the following to /etc/syslog.conf:
            *-------------------------------------------
            | #(Config::Patch-mypatch-append)
            | # Log my stuff
            | my.*         /var/log/my
            | #(Config::Patch-mypatch-append)
            | ...
            *-------------------------------------------

        # later on, to remove the patch:
        $patcher->remove();

DESCRIPTION
    "Config::Patch" helps changing configuration files, remembering the
    changes, and undoing them if necessary.

    Every change (patch) is marked by a *key*, which must be unique for the
    change, in order allow undoing it later on.

    To facilitate its usage, "Config::Patch" comes with a command line
    script that performs all functions:

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

            # Patch a file by search-and-replace
        echo "none:" | config-patch -s 'all:.*' -k key -f config_file

            # Comment out sections matched by a regular expression:
        config-patch -c '(?ms-xi:^all:.*?\n\n)' -k key -f config_file

            # Remove a previously applied patch
        config-patch -r -k key -f textfile

    Note that 'patch' doesn't refer to a patch in the format used by the
    *patch* program, but to an arbitrary section of text inserted into a
    file. Patches are line-based, "Config::Patch" always adds/removes entire
    lines.

  Specify a different comment character
    "Config::Patch" assumes that lines starting with a comment character are
    ignored by their applications. This is important, since "Config::Patch"
    uses comment lines to hides vital patch information in them for
    recovering from patches later on.

    By default, this comment character is '#', usable for file formats like
    YAML, Makefiles, and Perl. To change this default and use a different
    character, specify the comment character like

        my $patcher = Config::Patch->new( 
            comment_char => ";",  # comment char is now ";"
            # ...
        );

    in the constructor call. The command line script "config-patch" expects
    a different comment character with the "-C" option, check its manpage
    for details. Make sure to use the same comment character for patching
    and unpatching, otherwise chaos will ensue.

    Other than that, "Config::Patch" is format-agnostic. If you need to pay
    attention to the syntax of the configuration file to be patched, create
    a subclass of "Config::Patch" and put the format specific logic there.

    You can only patch a file *once* with a given key. Note that a single
    patch might result in multiple patched sections within a file if you're
    using the "replace()" or "comment_out()" methods.

    To apply different patches to the same file, use different keys. They
    can be can rolled back separately.

METHODS
    "$patcher = Config::Patch->new(file => $file, key => $key)"
        Creates a new patcher object. Optionally, exclusive updates are
        ensured by flocking if the "flock" parameter is set to 1:

            my $patcher = Config::Patch->new(
                file  => $file, 
                key   => $key,
                flock => 1,
            );

    "$patcher->append($textstring)"
        Appends a text string to the config file.

    "$patcher->prepend($textstring)"
        Adds a text string to the beginning of the file.

    "$patcher->remove()"
        Remove a previously applied patch. The patch key has either been
        provided with the constructor call previously or can be supplied as
        "key => $key".

    "$patcher->patched()"
        Checks if a patch with the given key was applied to the file
        already. The patch key has either been provided with the constructor
        call previously or can be supplied as "key => $key".

    "$patcher->replace($search, $replace)"
        Patches by searching for a given pattern $search (regexp) and
        replacing it by the text string $replace. Example:

                # Replace the 'all:' target in a Makefile and all 
                # of its production rules by a dummy rule.
            $patcher->replace(qr(^all:.*?\n\n)sm, 
                              "all:\n\techo 'all is gone!'\n");

        Note that the replace command will replace *the entire line* if it
        finds that a regular expression is matching a partial line.

        CAUTION: Make sure your $search patterns only cover the areas you'd
        like to replace. Multiple matches within one line are ignored, and
        so are matches that overlap with areas patched with different keys
        (*forbidden zones*).

    "$patcher->comment_out($search)"
        Patches by commenting out config lines matching the regular
        expression $search. Example:

                # Remove the 'all:' target and its production rules
                # from a makefile
            $patcher->comment_out(qr(^all:.*?\n\n)sm);

        Commenting out is just a special case of "replace()". Check its
        documentation for details.

    "$patcher->key($key)"
        Set a new patch key for applying subsequent patches.

    "($arrayref, $hashref) = $patcher->patches()"
        Examines the file and locates all patches.

        It returns two results: $arrayref, a reference to an array, mapping
        patch keys to the text of the patched sections:

            $arrayref = [ ['key1', 'patchtext1'], ['key2', 'patchtext2'],
                          ['key2', 'patchtext3'] ];

        Note that there can be several patched sections appearing under the
        same patch key (like the two non-consecutive sections under "key2"
        above).

        The second result is a reference $hashref to a hash, holding all
        patch keys as keys. Its values are the number of patch sections
        appearing under a given key.

LIMITATIONS
    "Config::Patch" assumes that a hashmark (#) at the beginning of a line
    in the configuration file marks a comment.

COPYRIGHT AND LICENSE
    Copyright 2005 by Mike Schilli. This library is free software; you can
    redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR
    2005, Mike Schilli <cpan@perlmeister.com>