ref: 24677b0d857051fc2a952c1dbceaeefa540d89d6
parent: 57d8a0bd95309bcc221850b263acdccc4e81b6ea
author: kvik <kvik@a-b.xyz>
date: Wed Apr 8 12:53:13 EDT 2020
Introduce text substitution helper subst(1) Using naive string concatenation to build sed substitution commands causes problems when the variable text being pasted contains embedded separator characters. Consider: ; prefix='/path/user@host' ; sed 's@^'$prefix'@@': sed: @: command garbled: s@^/path/user@host@@: To fix and avoid such problems we introduce subst(1), a helper utility working reliably with any regular expression and substitute text arguments, as well as providing some convenience. The above sed command becomes: ; subst '^'$prefix
--- a/clone
+++ b/clone
@@ -71,7 +71,7 @@
git/fs
@ {builtin cd $tree && tar cif /fd/1 .} | @ {tar xf /fd/0} \
|| die 'checkout failed:' $status
- for(f in `$nl{walk -f $tree | sed 's@^'$tree'/*@@'}){
+ for(f in `$nl{walk -f $tree | subst '^'$tree'/*'}){
if(! ~ $#f 0){
idx=.git/index9/tracked/$f
mkdir -p `$nl{basename -d $idx}
--- a/common.rc
+++ b/common.rc
@@ -11,11 +11,30 @@
exit 'usage'
}
+# subst [-g] this [that]
+fn subst{
+ awk 'BEGIN{
+ global = 0
+ for(i = 1; ARGV[i] ~ /^-/; i++){
+ if(ARGV[i] == "-g")
+ global = 1
+ ARGC--
+ }
+ this = ARGV[i++]; ARGC--
+ that = ARGV[i++]; ARGC--
+ }
+ {
+ if(global) gsub(this, that)
+ else sub(this, that)
+ }' $*
+}
+
fn gitup{
gitroot=`{git/conf -r >[2]/dev/null}
if(~ $#gitroot 0)
die 'not a git repository'
- gitrel=`{pwd | sed 's@^'$gitroot'/*@@'}
+ gitrel=`{pwd | subst '^'$"gitroot'/?'}
if(~ $#gitrel 0)
gitrel='.'
cd $gitroot
--- a/merge
+++ b/merge
@@ -12,7 +12,7 @@
theirbr=$3/tree
all=`{walk -f $ourbr $basebr $theirbr | \
- sed 's@^('$ourbr'|'$basebr'|'$theirbr')/*@@g' | sort | uniq}
+ subst -g '^('$ourbr'|'$basebr'|'$theirbr')/*' | sort | uniq}
for(f in $all){
ours=$ourbr/$f
base=$basebr/$f
--- a/pull
+++ b/pull
@@ -74,7 +74,7 @@
exit
local=`{git/branch}
-remote=`{git/branch | sed 's@^(refs/)?heads@remotes/'$upstream'@'}
+remote=`{git/branch | subst '^(refs/)?heads' 'remotes/'$upstream}
# we have local commits, but the remote hasn't changed.
# in this case, we want to keep the local commits untouched.
--- a/push
+++ b/push
@@ -52,7 +52,7 @@
updates=`$nl{git/send $force $branch $remove $remote || die $status}
for(ln in $updates){
u=`{echo $ln}
- refpath=`{echo $u(2) | sed 's@^refs/heads/@.git/refs/remotes/'$upstream'/@g'}
+ refpath=`{echo $u(2) | subst '^refs/heads/' '.git/refs/remotes/'$upstream'/'}
switch($u(1)){
case update;
mkdir -p `{basename -d $refpath}