X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?a=blobdiff_plain;f=cp-update;h=f4d66bee8ea70af10f0b7437b732ff6651503cd7;hb=dd60228fb054bcc7ad1f222d1de6c7f351c00069;hp=2207c407d1b8a7eab26066fd5dfe1fe65671b5e9;hpb=dbb7399cf634ebc433853bf4870789e424debf98;p=carnet-tools-cn.git diff --git a/cp-update b/cp-update index 2207c40..f4d66be 100755 --- a/cp-update +++ b/cp-update @@ -3,6 +3,7 @@ ## Copyright (C) 1998 Hrvoje Niksic ## Modification by Zeljko Boros (block entries, removing old entries) ## More options and use strict by Zoran Dzelajlija on 2004-02-24 +## Quite a few improvements by Damir Dzeko on 2005-03-18 (see bellow) ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -22,7 +23,7 @@ ## -> reformated code, introduced coding conventions ## -> increased reliability through atomic actualization ## -> everything is done in the memory - more mem, less i/o -## -> removed append mode - in-place editing considered harmfull +## -> removed append mode - in-place editing considered harmful ## -> added in-place mode as option use strict; @@ -54,12 +55,16 @@ $UsageLong = " -r | --remove Remove entry PACKAGE from FILE. Default is to add lines from stdin. + -x | --change Modify existing block, or add it if + it does not exist but the begin mark + can be found. + -m | --allow-multiple Allow multiple blocks of the same type. By default, old blocks are replaced with the new one. -h | --help Print this message (usage reference). - + --version Print version message. - Placement control: @@ -69,7 +74,6 @@ $UsageLong = " -i | --insert-after x Insert after this/matching line. -f | --insert-before x Insert before this/matching line. - -R | --regexp-match Use regexp mode for line matching. - Manipulating block marks: @@ -116,10 +120,12 @@ use constant INSERT_ON_TOP => 3; # InsertRemove modes use constant DO_REMOVE => 0; use constant DO_INSERT => 1; +use constant DO_CHANGE => 2; # Operation defaults $InsertRemove = DO_INSERT; $Placement = APPEND_AT_END; +$RegexpMatch = 1; $Comment = '#'; $CommentEnd = ''; $MatchLine = ''; @@ -139,6 +145,9 @@ while (@ARGV) { elsif (/^-r$/ || /^--remove$/) { $InsertRemove = DO_REMOVE; } + elsif (/^-x$/ || /^--change$/) { + $InsertRemove = DO_CHANGE; + } elsif (/^-m$/ || /^--allow-multi(?:ple)?$/) { $Multi = 1; } @@ -166,7 +175,7 @@ while (@ARGV) { $Placement = INSERT_ON_TOP; } elsif (/^-R$/ || /^--regexp(?:-match|-mode)?$/) { - $RegexpMatch = 1; + $RegexpMatch = 1; # it's the default } elsif (/^-h$/ || /^--help$/) { die $UsageLong; @@ -190,6 +199,10 @@ while (@ARGV) { unshift(@ARGV, $_); last; } + + if ($Multi and DO_CHANGE == $InsertRemove) { + die "$ProgramName: Cannot use both `--change' and `--allow-multiple'\n"; + } } $Package = shift or die $UsageShort; @@ -239,7 +252,11 @@ do_it() and exit(0); sub do_it { slurp(); - if (DO_INSERT == $InsertRemove) { + if (DO_CHANGE == $InsertRemove) { + $StdinContent = &stdin_content; + change() or add(); + } + elsif (DO_INSERT == $InsertRemove) { $StdinContent = &stdin_content; del() unless $Multi; add(); @@ -299,8 +316,8 @@ sub add() { } ++ $lineNo; } - if (! $added) { - warn "$ProgramName: Inserting lines at the end implicitly!\n"; + if ($MatchLine and ! $added) { + warn "$ProgramName: Inserting lines at the end implicitly! No '$MatchLine'\n"; push(@Lines, $StdinContent); } } @@ -338,6 +355,51 @@ sub del() { return scalar(@Lines); # whatever } +sub change() { + my ($mytrailer, $mybegin, $myend) = + ($Trailer, $MarkBegin, $MarkEnd); + + my ($bm_found, $em_found); # begin/end mark found indicator + + # Make the strings regexp-friendly by quoting non-word chars. + $mybegin =~ s/\W/\\$&/g; + $myend =~ s/\W/\\$&/g; + $mytrailer =~ s/\W/\\$&/g; + + my (@filtered, $done, $skip); + $done = 0; # job done once + $skip = 0; # skip original block + foreach (@Lines) { + if (! $done and $skip > 0) { + if (/^$myend(?:$mytrailer)?$/o) { + ++ $done; # skipped all that was to skip + } else { + ++ $skip; # count lines being skipped + } + } + elsif (0 == $skip and $_ =~ /^$mybegin(?:$mytrailer)?$/o) { + push (@filtered, $StdinContent); + $skip = 1; + } + else { + push (@filtered, $_) + } + # for safety check: + $bm_found = 1 if (/^$mybegin(?:$mytrailer)?$/o); + $em_found = 1 if (/^$myend(?:$mytrailer)?$/o); + } + if ($bm_found and $em_found) { + -- $skip; # correct the counter + DEBUG and print STDERR "Replaced block of $skip lines\n"; + @Lines = @filtered; + } + elsif ($bm_found and ! $em_found) { + # safety exit + die "$ProgramName: no end-mark after begin-mark!\n"; + } + return $done; +} + # written by ddzeko@srce.hr, 2005-03-18 # to improve reliabilitah :) #