summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Bini <michele.bini@gmail.com>2018-03-18 02:05:26 (GMT)
committerMichele Bini <michele.bini@gmail.com>2018-03-18 02:05:26 (GMT)
commitff795e52a1769cb48745257edc4dc6758578ba15 (patch)
treeddfd4af60960a1f35bdc672b4e43819bdea2395e
Added: git-sed
-rwxr-xr-xgit-sed189
1 files changed, 189 insertions, 0 deletions
diff --git a/git-sed b/git-sed
new file mode 100755
index 0000000..ec70ae8
--- /dev/null
+++ b/git-sed
@@ -0,0 +1,189 @@
+#!/bin/sh
+
+# Copyright (c) 2011, 2013, 2014, 2015 Michele Bini
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the version 3 of the GNU General Public License
+# as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -e
+
+usage() {
+ echo "Invalid invocation. For more info: $0 --usage"
+}
+
+println() {
+ printf "%s\n" "$*"
+}
+
+warn() {
+ println "$0: $*" >&2
+}
+
+die() {
+ warn "$*"
+ exit 1
+}
+
+if [ -z "$1" ]; then usage; exit 1; fi
+
+xargln() {
+ while IFS="" read -r line; do
+ "$@" "$line" </dev/tty
+ done
+}
+
+greprx="^"
+gitsed_greprx() { # REGEXP - Select only files matching REGEXP
+ greprx="$1"; shift; args "$@"
+}
+
+gitsed_sedopts() { # ARGS - Pass ARGS to sed
+ SEDOPTS="$1"; shift; args "$@"
+}
+
+test=""
+gitsed_test() { # - When combined with sed 'p' modifer, print lines that would change, without applying any actual change.
+ test=1; args "$@"
+}
+
+backupext=""
+gitsed_backupext() { # EXT - Backup files before changing them to fileEXT
+ backupext=1
+ (echo -n "$backupext"|grep -q "[^a-zA-Z0-9$.]") && die "Invalid alphanumeric characters in --backupext"
+ args "$@"
+}
+
+gitsed_usage() { # - Print help
+ echo Usage: git-sed OPTIONS* -- SEDEXPR FILES*
+ echo
+ echo Options:
+ sed -n "s/^gitsed_/ --/g;T;s/() {//;s/ *# / /;p" <"$0"
+}
+
+content=""
+filenames=""
+
+gitsed_content() { # - Apply sed expression to content.
+ content=1
+ args "$@"
+}
+
+gitsed_filenames() { # - Apply sed expression to filenames.
+ filenames=1
+ args "$@"
+}
+
+gitsed_both() { # - Apply sed expression to both content and filenames
+ content=1
+ filenames=1
+ args "$@"
+}
+
+force_unstaged=""
+gitsed_force() { # - Continue even in the presence of unstable changes
+ force_unstaged=1
+ args "$@"
+}
+
+gitsed_help() {
+ gitsed_usage "$@"
+}
+
+gitsed_debug() {
+ set -x; args "$@"
+}
+
+xargln() {
+ while IFS="" read -r line; do
+ "$@" "$line"
+ done
+}
+
+dosed() {
+ fname="$1"
+ if [ -n "$test" ]; then
+ sed -n $SEDOPTS -- "$sedexpr" <"$fname"
+ else
+ sed $SEDOPTS -- "$sedexpr" "$fname" && git update-index -- "$fname"
+ fi
+}
+
+mover() {
+ filename="$1"
+ newname="$(println "$filename"|sed $SEDOPTS -- "$sedexpr")"
+ if [ "$filename" = "$newname" ]; then :; else
+ mkdir -p "$(dirname "$newname")"
+ if [ -n "$test" ]; then
+ echo "Would rename $filename to $newname"
+ else
+ git mv -v -- "$filename" "$newname"
+ fi
+ fi
+}
+
+listfiles() {
+ git grep --no-full-name -l -e "^" -- "$@"
+ # git ls-files "$@"
+}
+
+apply() {
+ if [ -n "$test" ]; then
+ SEDOPTS="$SEDOPTS -n"
+ backupexit=""
+ fi
+
+ sedexpr="$1"
+
+ [ -z "$sedexpr" ] && die "You didn't specify a sed expression"
+
+ shift
+
+ if [ -z "$filenames" ] && [ -z "$content" ]; then
+ die "You need to add a --filenames, --content or --both option."
+ fi
+
+ if [ -n "$filenames" ]; then
+ listfiles "$@" | xargln mover
+ fi
+
+ if [ -z "$force_unstaged" ]; then
+ git diff --quiet -- "$@" || die "There are unstaged changes. Please stage or discard them before running git-sed."
+ fi
+
+ if [ -n "$test" ]; then
+ true
+ elif [ -n "$backupext" ]; then
+ SEDOPTS="$SEDOPTS -i$backupext"
+ else
+ SEDOPTS="$SEDOPTS --in-place"
+ fi
+
+ if [ -n "$content" ]; then
+ git grep --no-full-name -l -e "$greprx" -- "$@"|xargln dosed
+ fi
+}
+
+args() {
+ if [ -n "$1" ]; then
+ N="$1"; shift
+ case "$N" in
+ --) apply "$@" ;;
+ -E) SEDOPTS="$SEDOPTS -E"
+ args "$@"
+ ;;
+ --*) gitsed_"${N#--}" "$@" ;;
+ *) apply "$N" "$@" ;;
+ esac
+ fi
+}
+
+args "$@"