ref: cb5eaa11386a1346a086e1672198854fdbebff3c
parent: f10ded757ffea343cf07e27cb0c504653444659f
author: Ori Bernstein <[email protected]>
date: Tue Oct 15 22:33:10 EDT 2019
Speed up git/checkout: only copy changed files.
--- a/git.1
+++ b/git.1
@@ -131,6 +131,9 @@
.B -f
.I filters
]
+[
+.I [files...]
+]
.SH DESCRIPTION
.PP
--- a/pull
+++ b/pull
@@ -1,4 +1,4 @@
-#!/bin/rc -e
+#!/bin/rc -ex
rfork en
@@ -6,45 +6,28 @@
'
fn update{
- update=$1
- branch=$2
- upstream=$3
- url=$4
- dir=$5
+ branch=$1
+ upstream=$2
+ url=$3
+ dir=$4
fetch=`{git/fetch -b $branch -u $upstream $url} |[2] tr '\x0d' '\x0a'
st=$status
- if(! ~ $st ''){
+ if(! ~ $st '|'){
echo fetch failed: $st
exit $st
}
- echo $fetch | awk -v 'update='^$update '
- function writeref(ref, hash)
- {
- outfile = ".git/"ref
- # we have local commits: nothing to do
- if(system("~ `{git/query ''HEAD "hash" @''} `{git/query "hash"}") == 0)
- exit("");
- # we have local commits *and* remote commits: request a merge
- if(system("~ `{git/query ''HEAD "hash" @''} `{git/query HEAD}") != 0){
- printf("git/merge %s\n", hash) > "/fd/2";
- exit("merge");
- }
- # we only have remote commits: update head
- system("mkdir -p `{basename -d "outfile"}");
- print hash > outfile;
- close(outfile);
- }
-
- /^remote/{
- if($2=="HEAD")
- next
-
- if(update)
- writeref($2, $3)
- gsub("^refs/heads", "refs/remotes/'$upstream'", $2)
- writeref($2, $3)
- }
+ echo $fetch | awk '
+ /^remote/{
+ if($2=="HEAD")
+ next
+ gsub("^refs/heads", "refs/remotes/'$upstream'", $2)
+ outfile = ".git/"ref
+ system("mkdir -p `{basename -d "outfile"}");
+ print hash > outfile;
+ print ref" => "hash > "/dev/fd/2"
+ close(outfile);
+ }
'
}
@@ -55,11 +38,17 @@
exit usage
}
-git/fs
branch=`{awk '$1=="branch"{print $2}' < /mnt/git/ctl}
remote=()
-update='true'
+checkout='true'
upstream=origin
+
+if(! cd `{git/conf -r}){
+ echo 'not in git repository' >[1=2]
+ exit notgit
+}
+git/fs
+
while(~ $1 -*){
switch($1){
case -u
@@ -70,7 +59,7 @@
branch=$2
shift
case -f
- update=''
+ checkout=()
case *
usage
}
@@ -86,25 +75,35 @@
exit upstream
}
-if(! cd `{git/conf -r})
- exit 'not in git repository'
+update $branch $upstream $remote
+if (~ $#checkout 0)
+ exit
-dir=/mnt/git/branch/$branch/tree
-if(! ~ git/walk -q){
- echo 'repository is dirty; commit before pulling' >[1=2]
- exit 'dirty'
+local=`{git/branch}
+remote=`{git/branch | sed 's@^(refs/)?heads@remotes/'$upstream'@'}
+echo 'remote='$remote
+modified=`$nl{git/query -c HEAD $remote | grep '^[+~]' | sed 's/^..//'}
+deleted=`$nl{git/query -c HEAD $remote | grep '^-' | sed 's/^..//'}
+if(~ foo bar) { #! ~ $#modified 0 || ! ~ $#deleted 0){
+ if(! git/walk -q $modified $deleted){
+ echo remote changes would clobber local changes >[1=2]
+ exit dirty
+ }
}
-oldfiles=`$nl{git/walk -cfT}
-update $update $branch $upstream $remote $dir
-if(! ~ $update 0){
- rm -f $oldfiles
- tree=/mnt/git/HEAD/tree
- @{builtin cd $tree && tar cif /fd/1 .} | @{tar xf /fd/0}
- for(f in `$nl{walk -f $tree | sed 's@^'$tree'/*@@'}){
- if(! ~ $#f 0){
- idx=.git/index9/tracked/$f
- mkdir -p `{basename -d $idx}
- walk -eq $f > $idx
- }
+
+
+cp .git/refs/$remote .git/refs/$local
+if(! ~ $#modified 0){
+ for(m in `{walk -f $modified}){
+ gm=/mnt/git/HEAD/tree/$m
+ d=`{basename -d $m}
+ mkdir -p $d
+ mkdir -p .git/index9/tracked/$d
+ cp $gm $m
+ walk -eq $m > .git/index9/tracked/$m
}
+}
+if(! ~ $#deleted 0){
+ rm -f $deleted
+ rm -f .git/index9/tracked/$deleted
}
--- a/walk.c
+++ b/walk.c
@@ -210,7 +210,7 @@
void
usage(void)
{
- fprint(2, "usage: %s [-qbc] [-f filt]\n", argv0);
+ fprint(2, "usage: %s [-qbc] [-f filt] [paths...]\n", argv0);
exits("usage");
}
@@ -255,10 +255,20 @@
sysfatal("git/fs does not seem to be running");
if(printflg == 0)
printflg = Tflg | Aflg | Mflg | Rflg;
- if(access(TDIR, AEXIST) == 0 && readpaths(&r, TDIR, "") == -1)
- sysfatal("read tracked: %r");
- if(access(RDIR, AEXIST) == 0 && readpaths(&r, RDIR, "") == -1)
- sysfatal("read removed: %r");
+ if(argc == 0){
+ if(access(TDIR, AEXIST) == 0 && readpaths(&r, TDIR, "") == -1)
+ sysfatal("read tracked: %r");
+ if(access(RDIR, AEXIST) == 0 && readpaths(&r, RDIR, "") == -1)
+ sysfatal("read removed: %r");
+ }else{
+ r.path = emalloc(argc*sizeof(char*));
+ r.pathsz = argc;
+ for(i = 0; i < argc; i++){
+ snprint(tpath, sizeof(tpath), TDIR"/%s", argv[i]);
+ if(access(tpath, AEXIST) == 0)
+ r.path[r.npath++] = estrdup(argv[i]);
+ }
+ }
dedup(&r);
for(i = 0; i < r.npath; i++){