ref: cfebf83947550f3ae730cef4a9b1ab6bf6b8d4f7
parent: e524e8d65a7573c46d7beb49e77bfc2d55a5563d
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Aug 17 00:31:15 EDT 2021
git: better handling of absolute paths, regex metachars
Git currently gets a bit confused if you try to
manipulate files by absolute path. There were also a
number of places where user-controlled file paths ended
up getting passed to regex interpretation, which could
confuse things.
This change mainly does 2 things:
- Adds a 'drop' function which drops
a non-regex prefix from a string, and uses
that to manipulate paths, simplifies 'subst',
and removes 'subst -g', which was only used
with fixed regexes; sed does this job fine.
- When getting a path from a user, we
make it absolute and then strip out the head
Along the way it cleans up a couple of stupids:
- 'for(f in $list) if(! ~ $#f 0) use $f:
$f can't be a nil list because of
list flattening.
- removes a useless substitution here:
all=`$nl{{git/query -c $1 $2; git/query -c $2 $3} | sed 's/^..//' | \
gsubst '^('$ourbr'|'$basebr'|'$theirbr')/*' | sort | uniq}
where git/query -c doesn't produce
paths prefixed with the query.
--- a/sys/lib/git/common.rc
+++ b/sys/lib/git/common.rc
@@ -11,23 +11,22 @@
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--
- }
+fn subst {+ awk '
+ BEGIN{ARGC=0}+ {sub(ARGV[1], ARGV[2]); print}+ ' $*
+}
+
+fn drop {+ awk '
+ BEGIN{ARGC=0} {- if(global) gsub(this, that)
- else sub(this, that)
+ if(index($0, ARGV[1]) == 1)
+ $0=substr($0, length(ARGV[1])+1)
- }' $*
+ }
+ ' $*
}
fn present {@@ -77,7 +76,7 @@
if(~ $#gitroot 0)
die 'not a git repository'
gitfs=$gitroot/.git/fs
- gitrel=`{pwd | subst '^'$"gitroot'/?'}+ gitrel=`{pwd | drop $gitroot | sed 's@^/@@'}if(~ $#gitrel 0)
gitrel='.'
cd $gitroot
--- a/sys/src/cmd/git/add
+++ b/sys/src/cmd/git/add
@@ -16,11 +16,11 @@
if(~ $#* 0)
exec aux/usage
-paths=`$nl{cleanname -d $gitrel $*}+paths=`$nl{cleanname -d $gitrel $* | drop $gitroot}if(~ $add tracked)
- files=`$nl{walk -f $paths}+ files=`$nl{walk -f ./$paths}if not
- files=`$nl{cd .git/index9/tracked/ && walk -f $paths}+ files=`$nl{cd .git/index9/tracked/ && walk -f ./$paths} for(f in $files){ if(! ~ `$nl{cleanname $f} .git/*){--- a/sys/src/cmd/git/clone
+++ b/sys/src/cmd/git/clone
@@ -7,7 +7,7 @@
if(~ $debug 1)
debug=(-d)
-remote=`{echo $1 | subst -g '/*$'}+remote=`{echo $1 | sed 's@/*$@@'}local=$2
if(~ $#remote 0)
@@ -79,7 +79,7 @@
tree=.git/fs/HEAD/tree
lbranch=`{git/branch}- rbranch=`{echo $lbranch | subst '^heads' 'remotes/origin'}+ rbranch=`{echo $lbranch | subst 'heads' 'remotes/origin'}echo checking out repository...
if(test -f .git/refs/$rbranch){cp .git/refs/$rbranch .git/refs/$lbranch
@@ -86,12 +86,10 @@
git/fs
@ {builtin cd $tree && tar cif /fd/1 .} | @ {tar xf /fd/0} \|| die 'checkout failed:' $status
- for(f in `$nl{walk -f $tree | subst '^'$tree'/*'}){- if(! ~ $#f 0){- idx=.git/index9/tracked/$f
- mkdir -p `$nl{basename -d $idx}- walk -eq $f > $idx
- }
+ for(f in `$nl{walk -f $tree | drop $tree}){+ idx=.git/index9/tracked/$f
+ mkdir -p `$nl{basename -d $idx}+ walk -eq ./$f > $idx
}
}
if not{--- a/sys/src/cmd/git/merge
+++ b/sys/src/cmd/git/merge
@@ -7,13 +7,12 @@
basebr=$gitfs/object/$2/tree
theirbr=$gitfs/object/$3/tree
- all=`$nl{{git/query -c $1 $2; git/query -c $2 $3} | sed 's/^..//' | \- subst -g '^('$ourbr'|'$basebr'|'$theirbr')/*' | sort | uniq}+ all=`$nl{{git/query -c $1 $2; git/query -c $2 $3} | sed 's/^..//' | sort | uniq} for(f in $all){ours=$ourbr/$f
base=$basebr/$f
theirs=$theirbr/$f
- merge1 $f $theirs $base $ours
+ merge1 ./$f $theirs $base $ours
}
}
--- a/sys/src/cmd/git/pull
+++ b/sys/src/cmd/git/pull
@@ -75,8 +75,8 @@
# The remote is directly ahead of the local, and we have
# no local commits that need merging.
if(~ $#quiet 0)
- git/log -s -e $local'..'$remote >[1=2]
+ git/log -s -e $local'..'$remote
echo
-echo $remote':' `{git/query $local} '=>' `{git/query $remote} >[1=2]+echo $remote':' `{git/query $local} '=>' `{git/query $remote}git/branch -mnb $remote $local
exit ''
--- a/sys/src/cmd/git/revert
+++ b/sys/src/cmd/git/revert
@@ -11,8 +11,8 @@
if(~ $#query 1)
commit=`{git/query -p $query}-files=`$nl{cleanname -d $gitrel $*}-for(f in `$nl{cd $commit/tree/ && walk -f $files}){+files=`$nl{cleanname -d $gitrel $* | drop $gitroot}+for(f in `$nl{cd $commit/tree/ && walk -f ./$files}){ mkdir -p `{basename -d $f}cp -x -- $commit/tree/$f $f
git/add $f
--
⑨