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.
This commit is contained in:
Cody Boone Ferguson committed 2023-04-19 03:15:29 -07:00
1 parent fae013b322
commit baf357a23f
2 files changed
+115 -34

No files matched your search

+27 -12
View File
@@ -5,28 +5,33 @@
# #
# This script allows one to run sed under git control without having to come up # This script allows one to run sed under git control without having to come up
# with a list of files first and then passing those to the command. # with a list of files first and then passing those to the command.
#
# It allows for multiple sed commands and multiple globs. By default it uses -i # It allows for multiple sed commands and multiple globs. By default it uses -i
# to edit the file in place (without backup extension) but this can be # to edit the file in place (WITHOUT BACKUP EXTENSION; use -i option if you want
# overridden with the -I option. See -h option for all the options. # a backup!) but in place editing can be overridden with the -I option. See -h
# option for all the options.
# #
# DISCLAIMER AND WARNING: this is something of a hack and might be error prone. # DISCLAIMER AND WARNING: this is something of a hack and might be error prone.
# It works for what is needed but possibly could be improved. Even so I like it # It works for what is needed but possibly could be improved. Even so I like it
# how it is and I don't think it would do good to add any additional features # how it is and I don't think it would do much good to add many more additional
# except perhaps allowing for one to specify path to sed. # features.
# #
# - Cody Boone Ferguson (@xexyl) # - Cody Boone Ferguson (@xexyl)
# #
export SGIT_VERSION="0.0.7-1 12-04-2023" # format: major.minor.patch-release DD-MM-YYYY export SGIT_VERSION="0.0.8-1 19-04-2023" # format: major.minor.patch-release DD-MM-YYYY
USAGE="usage: $(basename "$0") [-h] [-V] [-v level] [-x] [-I] [-o sed_options] [-s sed] [-e command] <glob...> USAGE="usage: $(basename "$0") [-h] [-V] [-v level] [-x] [-I] [-i extension] [-o sed_options] [-s sed] [-e command] <glob...>
-h print help and exit -h print help and exit
-V print version and exit -V print version and exit
-v level set verbosity level -v level set verbosity level
-x turn on tracing (set -x) -x turn on tracing (set -x)
-I disable in place editing -I disable in place editing
-o sed options (don't pass '-') -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 WARNING: use of '-o n' without '-I', can depending on command, empty files
-s sed set path to sed -s sed set path to sed
-e command append sed command to to list to execute on globs -e command append sed command to to list to execute on globs
@@ -38,6 +43,7 @@ export SED
export SED_OPTIONS="" export SED_OPTIONS=""
export I_FLAG= export I_FLAG=
export VERBOSITY=0 export VERBOSITY=0
export EXTENSION=""
# we need an array for sed commands # we need an array for sed commands
declare -a SED_COMMANDS declare -a SED_COMMANDS
@@ -47,7 +53,7 @@ IFS=$'\t\n'
# parse args # parse args
# #
while getopts :hVv:xIo:s:e: flag; do while getopts :hVv:xIi:o:s:e: flag; do
case "$flag" in case "$flag" in
h) echo "$USAGE" 1>&2 h) echo "$USAGE" 1>&2
exit 2 exit 2
@@ -61,6 +67,8 @@ while getopts :hVv:xIo:s:e: flag; do
;; ;;
I) I_FLAG="-I" I) I_FLAG="-I"
;; ;;
i) EXTENSION="$OPTARG"
;;
o) SED_OPTIONS="-$OPTARG" o) SED_OPTIONS="-$OPTARG"
;; ;;
s) SED="$OPTARG" s) SED="$OPTARG"
@@ -148,6 +156,12 @@ if [[ "$VERBOSITY" -gt 1 ]]; then
echo "debug[2]: looping through all globs" 1>&2 echo "debug[2]: looping through all globs" 1>&2
fi fi
if [[ -n "$EXTENSION" ]]; then
if [[ "$VERBOSITY" -ge 1 ]]; then
echo "debug[1]: using backup extension: $EXTENSION" 1>&2
fi
fi
GLOBS="$#" GLOBS="$#"
i=0 i=0
while [[ "$i" -lt "$GLOBS" ]]; do while [[ "$i" -lt "$GLOBS" ]]; do
@@ -155,12 +169,13 @@ while [[ "$i" -lt "$GLOBS" ]]; do
echo "debug[2]: found glob: $i" 1>&2 echo "debug[2]: found glob: $i" 1>&2
fi fi
if [[ "$VERBOSITY" -ge 1 ]]; then if [[ "$VERBOSITY" -ge 1 ]]; then
if [[ -z "$I_FLAG" ]]; then if [[ -z "$I_FLAG" ]]; then
if [[ -n "$SED_OPTIONS" ]]; then if [[ -n "$SED_OPTIONS" ]]; then
echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"\" $SED_OPTIONS ${SED_COMMANDS[*]}" 1>&2 echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"$EXTENSION\" $SED_OPTIONS ${SED_COMMANDS[*]}" 1>&2
else else
echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"\" ${SED_COMMANDS[*]}" 1>&2 echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"$EXTENSION\" ${SED_COMMANDS[*]}" 1>&2
fi fi
else else
if [[ -n "$SED_OPTIONS" ]]; then if [[ -n "$SED_OPTIONS" ]]; then
@@ -173,9 +188,9 @@ while [[ "$i" -lt "$GLOBS" ]]; do
if [[ -z "$I_FLAG" ]]; then if [[ -z "$I_FLAG" ]]; then
if [[ -n "$SED_OPTIONS" ]]; then if [[ -n "$SED_OPTIONS" ]]; then
git ls-files "$1" | xargs "$SED" -i"" "$SED_OPTIONS" "${SED_COMMANDS[@]}" git ls-files "$1" | xargs "$SED" -i"$EXTENSION" "$SED_OPTIONS" "${SED_COMMANDS[@]}"
else else
git ls-files "$1" | xargs "$SED" -i"" "${SED_COMMANDS[@]}" git ls-files "$1" | xargs "$SED" -i"$EXTENSION" "${SED_COMMANDS[@]}"
fi fi
else else
if [[ -n "$SED_OPTIONS" ]]; then if [[ -n "$SED_OPTIONS" ]]; then
+88 -22
View File
@@ -7,36 +7,71 @@ 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 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 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 (though this always existed). The _default_ behaviour is to use in place editing
**WITHOUT A BACKUP EXTENSION** but you may override the saving to disk with the (**WITHOUT A BACKUP EXTENSION**; use `-i` to provide a backup extension) but you
`-I` option. can override the saving to disk with the `-I` option.
## Usage ## Usage
```sh ```sh
usage: sgit [-h] [-V] [-v level] [-x] [-I] [-o sed_options] [-s sed] [-e command] <glob...> usage: sgit [-h] [-V] [-v level] [-x] [-I] [-i extension] [-o sed_options] [-s sed] [-e command] <glob...>
-h print help and exit -h print help and exit
-V print version and exit -V print version and exit
-v level set verbosity level -v level set verbosity level
-x turn on tracing (set -x) -x turn on tracing (set -x)
-I disable in place editing -I disable in place editing
-o sed options (don't pass '-') -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 WARNING: use of '-o n' without '-I', can depending on command, empty files
-s sed set path to sed -s sed set path to sed
-e command append sed command to execute on globs -e command append sed command to to list to execute on globs
sgit version: 0.0.7-1 12-04-2023
sgit version: 0.0.8-1 19-04-2023
``` ```
You **MUST** specify at least one `sed` command and one glob: the sed command by 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 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 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:
```sh
./sgit -o n -e 's/.//g' sgit
```
because it would empty `sgit`!
# Examples # Examples
## Change in this file (in memory only) `\<sed\>` to be `used` but only show lines changed: ## Change in this file (_IN MEMORY ONLY_) `\<sed\>` to `used` but only show lines changed:
```sh ```sh
./sgit -I -o n -e 's/\<sed\>/used/p' README.md ./sgit -I -o n -e 's/\<sed\>/used/p' README.md
@@ -53,38 +88,69 @@ needs to be:
./sgit -I -o n -e '/\<sed\>/p' . ./sgit -I -o n -e '/\<sed\>/p' .
``` ```
## Change references of `\<sed\>` to be `used` in this file and save it: ## With tracing enabled, change references of `\<sed\>` to `used` in this file and save it:
```sh ```sh
./sgit -e 's/\<sed\>/used/p' -v3 -x README.md ./sgit -e 's/\<sed\>/used/g' -x README.md
``` ```
## Change `\<sed\>` to `used` but only if it's on the third line
## With tracing enabled, change references of `\<sed\>` to `used`, duplicating the lines, in this file and save it:
```sh ```sh
./sgit -e '3s/\<sed\>/used/g' README.md ./sgit -e 's/\<sed\>/used/p' -x README.md
```
## Verbosely (level 1) change references of `\<sed\>` to `used` in this file and save it:
```sh
./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`
```sh
./sgit -i.bak -e 's/\<sed\>/used/g' -v3 README.md
```
With that you would see something like:
```sh
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
```sh
./sgit -e '1s/\<sed\>/used/g' README.md
``` ```
Alternatively you could do one of: Alternatively you could do one of:
```sh ```sh
./sgit -e '3s/\<sed\>/u&/g' README.md ./sgit -e '1s/\<sed\>/u&/g' README.md
./sgit -e '3s/\(\<sed\>\)/u\1/g' README.md ./sgit -e '1s/\(\<sed\>\)/u\1/g' README.md
``` ```
# WARNING: invalid use of -o -n can empty files! ## Change `\<hack\>` to `crack` but only if it's on the third line
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:
```sh ```sh
./sgit -o n -e 's/.//g' sgit ./sgit -e '3s/\<hack\>/crack/g' README.md
``` ```
because it would empty `sgit`!
## Installation ## Installation