Files
ioccc/bin/sgit.README.md
T
Cody Boone Ferguson baf357a23f New version of sgit
Now supports backup extension.

Some warnings are noted in the usage (about backup extensions - one of
which goes for sed in general) and the README.md file.

Typo fixed the README.md file (some examples were in error for instance)
as well and add additional examples.

The new version corresponds to
https://github.com/xexyl/sgit/commit/9fccaa8cd680d3ed7cd91516710a5672630b5dff;
the README.md file had several new commits.
2023-04-19 03:15:29 -07:00

6.0 KiB

sgit - run sed on files under git control

This was originally a quick and dirty hack to modify files under git control via sed. It started out with some limitations like the inability to deal with spaces in sed commands, only allowing one glob and it had terrible efficiency because it ran git ls-files for each sed command.

Now it is a bit more thorough and is more efficient (though not perfect). It allows you to specify a path to sed, sed options and multiple sed commands (though this always existed). The default behaviour is to use in place editing (WITHOUT A BACKUP EXTENSION; use -i to provide a backup extension) but you can override the saving to disk with the -I option.

Usage

usage: sgit [-h] [-V] [-v level] [-x] [-I] [-i extension] [-o sed_options] [-s sed] [-e command] <glob...>

    -h			    print help and exit
    -V			    print version and exit
    -v level		    set verbosity level
    -x			    turn on tracing (set -x)
    -I			    disable in place editing
    -i extension	    set backup extension (default none)
				WARNING: sed -i overwrites existing files
				WARNING: this will create another file for each file changed
    -o			    sed options (NOTE: don't pass '-'!)
				WARNING: use of '-o n' without '-I', can depending on command, empty files
    -s sed		    set path to sed
    -e command		    append sed command to to list to execute on globs

sgit version: 0.0.8-1 19-04-2023

You MUST specify at least one sed command and one glob: the sed command by way of the -e option (just like with sed); anything after the last option is a glob. You may specify more than one of each. Specify -e for each command.

A note about the -i option and backup extensions

It works like sed -i except that the default behaviour of the script is to use -i just with an empty backup extension (this is required for some versions of sed which force that a backup extension actually be provided with the -i option .. I'm looking at you, BSD/macOS sed).

-i WARNING: each file edited will result in another file in the working directory

Of course if you have 50 files that are affected then 50 new files will be created.

-i WARNING: sed -i WILL OVERWRITE EXISTING FILES!

Please be aware that if a backup file already exists it WILL be overwritten! I won't even try and detect this because it's not how sed works and it would overly complicate the script.

-o n WARNING: invalid use of -o n can empty files!

Because sed -n does not print output if you do not use -I and you use substitute you can empty the entire file. For instance DO NOT do this:

./sgit -o n -e 's/.//g' sgit

because it would empty sgit!

Examples

Change in this file (IN MEMORY ONLY) \<sed\> to used but only show lines changed:

./sgit -I -o n -e 's/\<sed\>/used/p' README.md 
./sgit -I -n -e 's/\<sed\>/used/p' README.md 

Print out matches of \<sed\> in all files under git control

This is a simpler way of running git --no-pager grep -h -E '\<sed\>'|sed 's/^[0-9]*://g' which itself might or might not be more complicated than it needs to be:

./sgit -I -o n -e '/\<sed\>/p' .

With tracing enabled, change references of \<sed\> to used in this file and save it:

./sgit -e 's/\<sed\>/used/g' -x README.md

With tracing enabled, change references of \<sed\> to used, duplicating the lines, in this file and save it:

./sgit -e 's/\<sed\>/used/p' -x README.md

Verbosely (level 1) change references of \<sed\> to used in this file and save it:

./sgit -e 's/\<sed\>/used/g' -v1 README.md

Verbosely (level 3) change references of \<sed\> to used in this file with a backup as README.md.bak

./sgit -i.bak -e 's/\<sed\>/used/g' -v3 README.md

With that you would see something like:

debug[2]: sed commands:  -e	s/\<sed\>/used/g
debug[2]: looping through all globs
debug[1]: using backup extension: .bak
debug[2]: found glob: 0
debug[1]: about to run: git ls-files README.md | xargs /opt/local/bin/sed -i".bak" -e	s/\<sed\>/used/g
debug[2]: 0 remaining globs

Level 2 would not show how many globs remain after each operation.

Change \<sed\> to used but only if it's on the first line

./sgit -e '1s/\<sed\>/used/g' README.md

Alternatively you could do one of:

./sgit -e '1s/\<sed\>/u&/g' README.md
./sgit -e '1s/\(\<sed\>\)/u\1/g' README.md

Change \<hack\> to crack but only if it's on the third line

./sgit -e '3s/\<hack\>/crack/g' README.md

Installation

If you wish to install it you may either copy it to a place in your path or if you have make installed you can just run make install either as root or via sudo like:

sudo make install

Documentation?

Right now this is it but the Makefile is set up so that if a man page is added it can easily install it as well.

Limitations

One that comes to mind is you cannot specify git ls-files options but this could be problematic anyway especially if one were to specify the -z option.

There are probably other limitations but it works well for what I needed.

Bugs

None known but it does not try and determine which files have match the patterns. This would likely greatly complicate the script and is I feel unneeded.

If you specify invalid sed commands obviously there will be problems. If you specify invalid sed options there will possibly be problems as well.

Again this was originally a hack.

History

It has been a persistent problem for me that I need to edit files under git control and sed is the obvious way to go about it.

Working on the IOCCC mkiocccentry and the IOCCC temporary website and the IOCCC temporary website repos (and in particular the latter) is what inspired me to do something about it.

Other thoughts

Pull requests are welcome but I think it's mostly in a good enough state where this will probably generally not be needed.