#!/bin/rc -erfork ne. /sys/lib/git/common.rc fn findbranch{ branch=`{git/branch} if(test -e $gitfs/branch/$branch/tree){ refpath=.git/refs/$branch initial=false } if not if(test -e $gitfs/object/$branch/tree){ refpath=.git/HEAD initial=false } if not if(! test -e $gitfs/HEAD/tree){ refpath=.git/refs/$branch initial=true } if not die 'invalid branch:' $branch} # Remove commentary lines.# Remove leading and trailing empty lines.# Combine consecutive empty lines between paragraphs.# Remove trailing spaces from lines.# Ensure there's trailing newline.fn cleanmsg{ awk ' /^[ ]*#/ {next} /^[ ]*$/ {empty = 1; next} wet && empty {printf "\n"} {wet = 1; empty = 0} {sub(/[ ]+$/, ""); print $0} '} fn editmsg{ if(! test -s $msgfile.tmp){ >$msgfile.tmp { echo '# Author:' $name '<'$email'>' echo '#' for(p in $parents) echo '# parent:' $p git/walk -fAMR $files | subst '^' '# ' echo '#' echo '# Commit message:' } edit=1 } if(! ~ $#edit 0){ giteditor=`{git/conf core.editor} if(~ $#editor 0) editor=$giteditor if(~ $#editor 0) editor=hold $editor $msgfile.tmp } cleanmsg < $msgfile.tmp > $msgfile if(! test -s $msgfile) die 'empty commit message'} fn parents{ if(! ~ $#revise 0) parents=`{cat $gitfs/HEAD/parent} if not if(test -f .git/merge-parents) parents=`{cat .git/merge-parents | sort | uniq} if not if(~ $initial true) parents=() if not parents=`{git/query $branch}} fn commit{ msg=`''{cat $msgfile} if(! ~ $#parents 0) pflags='-p'^$parents hash=`{git/save -n $"name -e $"email -m $"msg $pflags $files || die $status}} fn update{ mkdir -p `{basename -d $refpath} # Paranoia: let's not mangle the repo. if(~ $#hash 0) die 'botched commit' rm -f .git/merge-parents echo $branch: $hash echo $hash > $refpath for(f in $files){ if(! test -e $f && ! test -e .git/object/$hash/tree/$f) echo R NOQID 0 $f >> .git/INDEX9 if not echo T NOQID 0 $f >> .git/INDEX9 }} fn filterdiff{ awk ' function dump(){ if(n == 0) return print "--- a/"f >>"/dev/cons" print "+++ b/"f >>"/dev/cons" for(i = 0; i < n; i++) print lines[i] >>"/dev/cons" printf("Commit this hunk?[n] ") >>"/dev/cons" getline ans < "/dev/cons" if(ans ~ /[yY]/) for(i = 0; i < n; i++) print lines[i] n = 0 } /^---/{ next } /^\+\+\+/{ f = substr($0, 5) print "--- "f print "+++ "f n = 0 next } /^@@/{ dump() } { lines[n++] = $0 } END{ dump() } '} fn pickhunks{ p=$wdir/patch if(test -f .git/fs/HEAD/tree/$i) #<[12]/fd/0 >[13]/fd/1 { diff -u .git/fs/HEAD/tree/$1 $1 | filterdiff >>$p } { diff -u .git/fs/HEAD/tree/$1 $1 | filterdiff >>$p } || status='' if not diff -u /dev/null $1 >>$p || status=''} fn apply{ t=$wdir/tree/ p=$wdir/patch ln=`{wc -l $p} if(test $ln(1) -lt 3) die 'no hunks seleted' # replace the global var so if no hunks were selected, we don't commit it files=`{patch -n $p} mkdir $t @{cd .git/fs/HEAD/tree; tar c $files >[2]/dev/null} | @{cd $t; tar xT} for(i in $files){ d=`{basename -d $i} if(! test -d $d){ mkdir -p $t/$d bind -bc $t/$d $d } } bind -bc $t . patch <$p >/dev/null || die 'failed partial patch: '^$status} gitup flagfmt='m:msg message, r:revise, e:edit, p:partial'; args='[file ...]'eval `''{aux/getflags $*} || exec aux/usage wdir=/mnt/gitramfs -m $wdirmsgfile=$wdir/git-msg.$pidif(~ $#msg 1) echo $msg >$msgfile.tmpif not if(~ $#revise 1){ msg=1 echo revising commit `{cat $gitfs/HEAD/hash} cat $gitfs/HEAD/msg >$msgfile.tmp} files=()if(test -f .git/merge-parents) files=`$nl{git/query -c `{cat .git/merge-parents} | sed 's/^..//'}if(! ~ $#* 0) files=($files `$nl{git/walk -fRMA -c `$nl{cleanname -d $gitrel $*}})if(~ $status '' || ~ $#files 0 && ! test -f .git/merge-parents && ~ $#revise 0) die 'nothing to commit'if(~ $#partial 1){ for(i in $files) pickhunks $i apply} @{ flag e + whoami findbranch parents editmsg commit update} || die 'could not commit:' $statusexit ''
#!/bin/rc -e
rfork ne
. /sys/lib/git/common.rc
fn findbranch{
branch=`{git/branch}
if(test -e $gitfs/branch/$branch/tree){
refpath=.git/refs/$branch
initial=false
}
if not if(test -e $gitfs/object/$branch/tree){
refpath=.git/HEAD
initial=false
}
if not if(! test -e $gitfs/HEAD/tree){
refpath=.git/refs/$branch
initial=true
}
if not
die 'invalid branch:' $branch
}
# Remove commentary lines.
# Remove leading and trailing empty lines.
# Combine consecutive empty lines between paragraphs.
# Remove trailing spaces from lines.
# Ensure there's trailing newline.
fn cleanmsg{
awk '
/^[ ]*#/ {next}
/^[ ]*$/ {empty = 1; next}
wet && empty {printf "\n"}
{wet = 1; empty = 0}
{sub(/[ ]+$/, ""); print $0}
'
}
fn editmsg{
if(! test -s $msgfile.tmp){
>$msgfile.tmp {
echo '# Author:' $name '<'$email'>'
echo '#'
for(p in $parents)
echo '# parent:' $p
git/walk -fAMR $files | subst '^' '# '
echo '#'
echo '# Commit message:'
}
edit=1
}
if(! ~ $#edit 0){
giteditor=`{git/conf core.editor}
if(~ $#editor 0)
editor=$giteditor
if(~ $#editor 0)
editor=hold
$editor $msgfile.tmp
}
cleanmsg < $msgfile.tmp > $msgfile
if(! test -s $msgfile)
die 'empty commit message'
}
fn parents{
if(! ~ $#revise 0)
parents=`{cat $gitfs/HEAD/parent}
if not if(test -f .git/merge-parents)
parents=`{cat .git/merge-parents | sort | uniq}
if not if(~ $initial true)
parents=()
if not
parents=`{git/query $branch}
}
fn commit{
msg=`''{cat $msgfile}
if(! ~ $#parents 0)
pflags='-p'^$parents
hash=`{git/save -n $"name -e $"email -m $"msg $pflags $files || die $status}
}
fn update{
mkdir -p `{basename -d $refpath}
# Paranoia: let's not mangle the repo.
if(~ $#hash 0)
die 'botched commit'
rm -f .git/merge-parents
echo $branch: $hash
echo $hash > $refpath
for(f in $files){
if(! test -e $f && ! test -e .git/object/$hash/tree/$f)
echo R NOQID 0 $f >> .git/INDEX9
if not
echo T NOQID 0 $f >> .git/INDEX9
}
}
fn filterdiff{
awk '
function dump(){
if(n == 0)
return
print "--- a/"f >>"/dev/cons"
print "+++ b/"f >>"/dev/cons"
for(i = 0; i < n; i++)
print lines[i] >>"/dev/cons"
printf("Commit this hunk?[n] ") >>"/dev/cons"
getline ans < "/dev/cons"
if(ans ~ /[yY]/)
for(i = 0; i < n; i++)
print lines[i]
n = 0
}
/^---/{ next }
/^\+\+\+/{
f = substr($0, 5)
print "--- "f
print "+++ "f
n = 0
next
}
/^@@/{ dump() }
{ lines[n++] = $0 }
END{ dump() }
'
}
fn pickhunks{
p=$wdir/patch
if(test -f .git/fs/HEAD/tree/$i)
#<[12]/fd/0 >[13]/fd/1 { diff -u .git/fs/HEAD/tree/$1 $1 | filterdiff >>$p }
{ diff -u .git/fs/HEAD/tree/$1 $1 | filterdiff >>$p } || status=''
if not
diff -u /dev/null $1 >>$p || status=''
}
fn apply{
t=$wdir/tree/
p=$wdir/patch
ln=`{wc -l $p}
if(test $ln(1) -lt 3)
die 'no hunks seleted'
# replace the global var so if no hunks were selected, we don't commit it
files=`{patch -n $p}
mkdir $t
@{cd .git/fs/HEAD/tree; tar c $files >[2]/dev/null} | @{cd $t; tar xT}
for(i in $files){
d=`{basename -d $i}
if(! test -d $d){
mkdir -p $t/$d
bind -bc $t/$d $d
}
}
bind -bc $t .
patch <$p >/dev/null || die 'failed partial patch: '^$status
}
gitup
flagfmt='m:msg message, r:revise, e:edit, p:partial'; args='[file ...]'
eval `''{aux/getflags $*} || exec aux/usage
wdir=/mnt/git
ramfs -m $wdir
msgfile=$wdir/git-msg.$pid
if(~ $#msg 1)
echo $msg >$msgfile.tmp
if not if(~ $#revise 1){
msg=1
echo revising commit `{cat $gitfs/HEAD/hash}
cat $gitfs/HEAD/msg >$msgfile.tmp
}
files=()
if(test -f .git/merge-parents)
files=`$nl{git/query -c `{cat .git/merge-parents} | sed 's/^..//'}
if(! ~ $#* 0)
files=($files `$nl{git/walk -fRMA -c `$nl{cleanname -d $gitrel $*}})
if(~ $status '' || ~ $#files 0 && ! test -f .git/merge-parents && ~ $#revise 0)
die 'nothing to commit'
if(~ $#partial 1){
for(i in $files)
pickhunks $i
apply
}
@{
flag e +
whoami
findbranch
parents
editmsg
commit
update
} || die 'could not commit:' $status
exit ''