X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=carnet-tools-cn.git;a=blobdiff_plain;f=cp-update;h=f4d66bee8ea70af10f0b7437b732ff6651503cd7;hp=d5b2ab24f80e7413ce0b39af4296e185fa9a9c4d;hb=baae9f008f06d16d8d033ba280c0552403c1b9bb;hpb=9d14d6fd31235bc0c8a6733fcf37cec81879dfcd diff --git a/cp-update b/cp-update index d5b2ab2..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: @@ -115,6 +120,7 @@ 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; @@ -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; } @@ -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(); @@ -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 :) #