I often make changes on my code-base and manually using sed, awk or perl -pi -e is not always as efficient as having a simple alias: git pie.
Furthermore, because I am working on Cygwin, I cannot do real in-place replacement without a temporary file that I have to manually suppress afterwards.
Last but not least, sed, awk and perl -pi -e touch all the files that make them new from the point of view of make. I rather want to touch only the file with real changes so I wrote this Git alias:
[alias]
# Replace
pie = "!f() { \
git ls-files -z | xargs -0 perl -e ' \
my $eval = shift @ARGV; \
foreach my $file (@ARGV) { \
next unless -f $file; \
open my $fd, \"<\", $file; \
my $content = do { local $/; <$fd>}; \
close $fd; \
my $new = do { $_ = $content; eval $eval; }; \
if ($content ne $new) { \
open my $fd, \">\", $file; \
print $fd $_; \
close $fd; \
} \
} \
' \"$1\"; }; f"
I am sure some simplifications can be made on this piece of code, so I ask for your opinion.
The usage is:
$ git pie s/foo/bar/g
I decided to slurp the whole file in memory in order to do multiline regexes which is very convenient sometime despite the performance.
There is perhaps a missing feature: the ability to exclude or include some file extensions only or simply allow this call:
$ git ls-files | grep -P '[.][ch]$' | xargs git pie s/foo/bar/
I still didn't figure out how I want to do it. One possible way is:
$ git pie 's/foo/bar/ if $file =~ /\.(ch)$/'
git | xargsdirectly in the alias? \$\endgroup\$echo 1 2 3 | xargs echo? You need to write it as follow:f() {echo 1 2 3 | xargs echo $1;}; f. Do you have a better option? \$\endgroup\$\"<\"when opening file for reading, as that's the default mode anyway. \$\endgroup\$-ioptions of perl & sed etc. The only thing I'd change is to makepiea standalone perl script in your $PATH (because it could be useful standalone and because reading and editing a perl script inside a couple of levels of quoting is harder than it needs to be, and all those EOL backslashes don't help). then just run thepiescript with xargs in your git alias. \$\endgroup\$open FH, MODE, EXPRis fine. it's a good habit to use it even when you don't need to. \$\endgroup\$