M add => add +0 -0
M branch => branch +9 -9
@@ 48,9 48,12 @@ if(~ $#newbr 0){
modified=`$nl{git/query -c HEAD $base | grep '^[^-]' | subst '^..'}
deleted=`$nl{git/query -c HEAD $base | grep '^-' | subst '^..'}
-if(! ~ $#modified 0 || ! ~ $#deleted 0 && ~ $#merge 0){
- git/walk -fRMA $modified $deleted ||
- die 'uncommited changes would be clobbered'
+# if we're not merging, don't clobber existing changes.
+if(~ $#merge 0){
+ if(! ~ $#modified 0 || ! ~ $#deleted 0){
+ git/walk -fRMA $modified $deleted ||
+ die 'uncommitted changes would be clobbered'
+ }
}
if(~ $delete 1){
rm -f .git/$new
@@ 68,8 71,6 @@ basedir=`{git/query -p $base}
dirtypaths=()
if(! ~ $#modified 0 || ! ~ $#deleted 0)
dirtypaths=`$nl{git/walk -cfRMA $modified $deleted}
-if(! ~ $#modified 0 || ! ~ $#deleted 0)
- dirtypaths=`$nl{git/walk -cfRMA $modified $deleted}
if(~ $#dirtypaths 0)
cleanpaths=($modified $deleted)
if not {
@@ 99,10 100,9 @@ for(m in $cleanpaths){
rm -rf .git/index9/tracked/$m
}
if(~ $b file){
- if(cp -x -- $basedir/tree/$m $m)
- walk -eq $m > .git/index9/tracked/$m
- if not
- echo -n > .git/index9/tracked/$m
+ cp -x -- $basedir/tree/$m $m
+ walk -eq $m > .git/index9/tracked/$m
+ touch $m
}
}
M clone => clone +1 -1
@@ 33,7 33,7 @@ fn clone{
echo '[remote "origin"]'
echo ' url='$remote
}
- {git/fetch $debug $branchflag $remote >[2=3] | awk '
+ {git/get $debug $branchflag $remote >[2=3] | awk '
BEGIN{
headref=""
if(ENVIRON["branch"] != "")
M commit => commit +2 -1
@@ 101,7 101,8 @@ fn update{
}
fn sigexit{
- rm -f $msgfile $msgfile.tmp
+ if(~ ! $#msgfile 0)
+ rm -f $msgfile $msgfile.tmp
}
gitup
M compat => compat +1 -1
@@ 131,7 131,7 @@ fn cmd_ls-remote{
remote=`$nl{git/conf 'remote "'$1'".url'}
if(~ $#remote 0)
remote=$1
- git/fetch -l $remote | awk '/^remote/{print $3"\t"$2}'
+ git/get -l $remote | awk '/^remote/{print $3"\t"$2}'
}
fn cmd_version{
M fs.c => fs.c +45 -14
@@ 70,13 70,14 @@ char *qroot[] = {
"ctl",
};
-#define Eperm "permission denied";
-#define Eexist "does not exist";
-#define E2long "path too long";
-#define Enodir "not a directory";
-#define Erepo "unable to read repo";
-#define Egreg "wat";
-#define Ebadobj "invalid object";
+#define Eperm "permission denied"
+#define Eexist "does not exist"
+#define E2long "path too long"
+#define Enodir "not a directory"
+#define Erepo "unable to read repo"
+#define Eobject "invalid object"
+#define Egreg "wat"
+#define Ebadobj "invalid object"
char gitdir[512];
char *username;
@@ 377,19 378,20 @@ objread(Req *r, Gitaux *aux)
static void
readcommitparent(Req *r, Object *o)
{
- char *buf, *p;
+ char *buf, *p, *e;
int i, n;
- n = o->commit->nparent * (40 + 2);
+ /* 40 bytes per hash, 1 per nl, 1 for terminator */
+ n = o->commit->nparent * (40 + 1) + 1;
buf = emalloc(n);
p = buf;
+ e = buf + n;
for (i = 0; i < o->commit->nparent; i++)
- p += sprint(p, "%H\n", o->commit->parent[i]);
- readbuf(r, buf, n);
+ p = seprint(p, e, "%H\n", o->commit->parent[i]);
+ readbuf(r, buf, p - buf);
free(buf);
}
-
static void
gitattach(Req *r)
{
@@ 623,9 625,9 @@ gitwalk1(Fid *fid, char *name, Qid *q)
e = objwalk1(q, o->obj, o, c, name, Qobject, aux);
}else{
if(hparse(&h, name) == -1)
- return "invalid object name";
+ return Eobject;
if((c->obj = readobject(h)) == nil)
- return "could not read object";
+ return Eobject;
if(c->obj->type == GBlob || c->obj->type == GTag){
c->mode = 0644;
q->type = 0;
@@ 804,6 806,34 @@ gitread(Req *r)
}
static void
+gitopen(Req *r)
+{
+ Gitaux *aux;
+ Crumb *c;
+
+ aux = r->fid->aux;
+ c = crumb(aux, 0);
+ switch(r->ifcall.mode&3){
+ default:
+ respond(r, "botched mode");
+ break;
+ case OWRITE:
+ respond(r, Eperm);
+ break;
+ case OREAD:
+ case ORDWR:
+ respond(r, nil);
+ break;
+ case OEXEC:
+ if((c->mode & 0111) == 0)
+ respond(r, Eperm);
+ else
+ respond(r, nil);
+ break;
+ }
+}
+
+static void
gitstat(Req *r)
{
Gitaux *aux;
@@ 829,6 859,7 @@ Srv gitsrv = {
.attach=gitattach,
.walk1=gitwalk1,
.clone=gitclone,
+ .open=gitopen,
.read=gitread,
.stat=gitstat,
.destroyfid=gitdestroyfid,
R fetch.c => get.c +34 -6
@@ 180,12 180,13 @@ fail(char *pack, char *idx, char *msg, ...)
int
fetchpack(Conn *c)
{
- char buf[Pktmax], *sp[3];
+ char buf[Pktmax], *sp[3], *ep;
char *packtmp, *idxtmp, **ref;
Hash h, *have, *want;
int nref, refsz, first;
- int i, n, req, pfd;
+ int i, n, l, req, pfd;
vlong packsz;
+ Objset hadobj;
Object *o;
nref = 0;
@@ 246,13 247,19 @@ fetchpack(Conn *c)
req = 1;
}
flushpkt(c);
+ osinit(&hadobj);
for(i = 0; i < nref; i++){
- if(hasheq(&have[i], &Zhash))
+ if(hasheq(&have[i], &Zhash) || oshas(&hadobj, have[i]))
continue;
+ if((o = readobject(have[i])) == nil)
+ sysfatal("missing object we should have: %H", have[i]);
+ osadd(&hadobj, o);
+ unref(o);
n = snprint(buf, sizeof(buf), "have %H\n", have[i]);
if(writepkt(c, buf, n + 1) == -1)
sysfatal("could not send have for %H", have[i]);
}
+ osclear(&hadobj);
if(!req)
flushpkt(c);
@@ 260,7 267,7 @@ fetchpack(Conn *c)
if(writepkt(c, buf, n) == -1)
sysfatal("write: %r");
if(!req)
- return 0;
+ goto showrefs;
if(readphase(c) == -1)
sysfatal("read: %r");
if((n = readpkt(c, buf, sizeof(buf))) == -1)
@@ 277,9 284,30 @@ fetchpack(Conn *c)
sysfatal("could not create %s: %r", packtmp);
fprint(2, "fetching...\n");
- packsz = 0;
+ /*
+ * Work around torvalds git bug: we get duplicate have lines
+ * somtimes, even though the protocol is supposed to start the
+ * pack file immediately.
+ *
+ * Skip ahead until we read 'PACK' off the wire
+ */
+ while(1){
+ if(readn(c->rfd, buf, 4) != 4)
+ sysfatal("fetch packfile: short read");
+ buf[4] = 0;
+ if(strncmp(buf, "PACK", 4) == 0)
+ break;
+ l = strtol(buf, &ep, 16);
+ if(l == 0 || ep != buf + 4)
+ sysfatal("fetch packfile: junk pktline");
+ if(readn(c->rfd, buf, l) != l)
+ sysfatal("fetch packfile: short read");
+ }
+ if(write(pfd, "PACK", 4) != 4)
+ sysfatal("write pack header: %r");
+ packsz = 4;
while(1){
- n = readn(c->rfd, buf, sizeof buf);
+ n = read(c->rfd, buf, sizeof buf);
if(n == 0)
break;
if(n == -1 || write(pfd, buf, n) != n)
M git.h => git.h +6 -5
@@ 4,6 4,7 @@
#include <flate.h>
#include <regexp.h>
+typedef struct Capset Capset;
typedef struct Conn Conn;
typedef struct Hash Hash;
typedef struct Delta Delta;
@@ 26,6 27,8 @@ enum {
Npackcache = 32,
Hashsz = 20,
Pktmax = 65536,
+ KiB = 1024,
+ MiB = 1024*KiB,
};
enum {
@@ 155,16 158,14 @@ struct Objset {
struct Qelt {
Object *o;
- vlong mtime;
+ vlong ctime;
int color;
- int dist;
};
struct Objq {
Qelt *heap;
int nheap;
int heapsz;
- int nkeep;
};
struct Dtab {
@@ 241,9 242,9 @@ struct Delta {
extern Reprog *authorpat;
extern Objset objcache;
+extern vlong cachemax;
extern Hash Zhash;
extern int chattygit;
-extern int cachemax;
extern int interactive;
#pragma varargck type "H" Hash
@@ 321,5 322,5 @@ void closeconn(Conn *);
/* queues */
void qinit(Objq*);
void qclear(Objq*);
-void qput(Objq*, Object*, int, int);
+void qput(Objq*, Object*, int);
int qpop(Objq*, Qelt*);
M import => import +8 -1
@@ 45,12 45,19 @@ fn apply @{
}
state=="headers" && /^$/ {
state="body"
- next
}
(state=="headers" || state=="body") && (/^diff / || /^---( |$)/){
state="diff"
}
+ state=="body" && /^[ ]*$/ {
+ empty=1
+ next
+ }
state=="body" {
+ if(empty)
+ printf "\n" > "/env/msg"
+ empty=0
+ sub(/[ ]+$/, "")
print > "/env/msg"
}
state=="diff" {
M log.c => log.c +3 -3
@@ 153,7 153,7 @@ show(Object *o)
Bprint(out, "Author:\t%s\n", o->commit->author);
if(o->commit->committer != nil
&& strcmp(o->commit->author, o->commit->committer) != 0)
- Bprint(out, "Commiter:\t%s\n", o->commit->committer);
+ Bprint(out, "Committer:\t%s\n", o->commit->committer);
Bprint(out, "Date:\t%Ï„\n", tmfmt(&tm, "WW MMM D hh:mm:ss z YYYY"));
Bprint(out, "\n");
p = o->commit->msg;
@@ 205,7 205,7 @@ showcommits(char *c)
sysfatal("load %H: %r", h);
qinit(&objq);
osinit(&done);
- qput(&objq, o, 0, 0);
+ qput(&objq, o, 0);
while(qpop(&objq, &e)){
show(e.o);
for(i = 0; i < e.o->commit->nparent; i++){
@@ 214,7 214,7 @@ showcommits(char *c)
if((p = readobject(e.o->commit->parent[i])) == nil)
sysfatal("load %H: %r", o->commit->parent[i]);
osadd(&done, p);
- qput(&objq, p, 0, 0);
+ qput(&objq, p, 0);
}
unref(e.o);
}
M mkfile => mkfile +1 -7
@@ 3,7 3,7 @@
BIN=/$objtype/bin/git
TARG=\
conf\
- fetch\
+ get\
fs\
log\
query\
@@ 51,12 51,6 @@ install:V:
mk $MKFLAGS $i.install
for (i in $RC)
mk $MKFLAGS $i.rcinstall
- cp git.1.man /sys/man/1/git
- cp gitfs.4.man /sys/man/4/gitfs
- cp common.rc /sys/lib/git/common.rc
-
-uninstall:V:
- rm -rf $BIN /sys/lib/git /sys/man/1/git /sys/man/4/gitfs
%.rcinstall:V:
cp $stem $BIN/$stem
M pack.c => pack.c +4 -5
@@ 65,8 65,8 @@ static Object *readidxobject(Biobuf *, Hash, int);
Objset objcache;
Object *lruhead;
Object *lrutail;
-int ncache;
-int cachemax = 4096;
+vlong ncache;
+vlong cachemax = 512*MiB;
Packf *packf;
int npackf;
int openpacks;
@@ 158,7 158,7 @@ cache(Object *o)
if(!(o->flag & Ccache)){
o->flag |= Ccache;
ref(o);
- ncache++;
+ ncache += o->size;
}
while(ncache > cachemax && lrutail != nil){
p = lrutail;
@@ 168,8 168,8 @@ cache(Object *o)
p->flag &= ~Ccache;
p->prev = nil;
p->next = nil;
+ ncache -= p->size;
unref(p);
- ncache--;
}
}
@@ 1036,7 1036,6 @@ retry:
return obj;
}
}
-
snprint(hbuf, sizeof(hbuf), "%H", h);
snprint(path, sizeof(path), ".git/objects/%c%c/%s", hbuf[0], hbuf[1], hbuf + 2);
M proto.c => proto.c +15 -2
@@ 220,14 220,27 @@ static int
issmarthttp(Conn *c, char *direction)
{
char buf[Pktmax+1], svc[128];
- int n;
+ int fd, n;
+
+ if((fd = webopen(c, "contenttype", OREAD)) == -1)
+ return -1;
+ n = readn(fd, buf, sizeof(buf) - 1);
+ close(fd);
+ if(n == -1)
+ return -1;
+ buf[n] = '\0';
+ snprint(svc, sizeof(svc), "application/x-git-%s-pack-advertisement", direction);
+ if(strcmp(svc, buf) != 0){
+ werrstr("dumb http protocol not supported");
+ return -1;
+ }
if((n = readpkt(c, buf, sizeof(buf))) == -1)
sysfatal("http read: %r");
buf[n] = 0;
snprint(svc, sizeof(svc), "# service=git-%s-pack\n", direction);
if(strncmp(svc, buf, n) != 0){
- werrstr("dumb http protocol not supported");
+ werrstr("invalid initial packet line");
return -1;
}
if(readpkt(c, buf, sizeof(buf)) != 0){
M pull => pull +1 -4
@@ 7,13 7,10 @@ fn update{
upstream=$2
url=$3
dir=$4
- bflag=()
dflag=()
- if(! ~ $#branch 0)
- bflag=(-b $branch)
if(! ~ $#debug 0)
dflag='-d'
- {git/fetch $dflag $bflag -u $upstream $url >[2=3] || die $status} | awk '
+ {git/get $dflag -u $upstream $url >[2=3] || die $status} | awk '
/^remote/{
if($2=="HEAD")
next
M ref.c => ref.c +57 -155
@@ 5,25 5,12 @@
#include "git.h"
typedef struct Eval Eval;
-typedef struct Lcaq Lcaq;
-
-struct Lcaq {
- Objq;
-
- Hash *head;
- Hash *tail;
- int nhead;
- int ntail;
-
- Object *best;
- int dist;
-};
-
enum {
Blank,
Keep,
Drop,
+ Skip,
};
struct Eval {
@@ 38,6 25,7 @@ static char *colors[] = {
[Keep] "keep",
[Drop] "drop",
[Blank] "blank",
+[Skip] "skip",
};
static Object zcommit = {
@@ 51,26 39,6 @@ eatspace(Eval *ev)
ev->p++;
}
-int
-objdatecmp(void *pa, void *pb)
-{
- Object *a, *b;
- int r;
-
- a = readobject((*(Object**)pa)->hash);
- b = readobject((*(Object**)pb)->hash);
- assert(a->type == GCommit && b->type == GCommit);
- if(a->commit->mtime == b->commit->mtime)
- r = 0;
- else if(a->commit->mtime < b->commit->mtime)
- r = -1;
- else
- r = 1;
- unref(a);
- unref(b);
- return r;
-}
-
void
push(Eval *ev, Object *o)
{
@@ 134,96 102,19 @@ take(Eval *ev, char *m)
}
static int
-pickbest(Lcaq *q, Qelt *e, int color)
-{
- int i, best, exact;
-
- best = 0;
- exact = 0;
- if(color == Blank || e->color == color)
- return 0;
- if(e->dist < q->dist){
- dprint(1, "found best (dist %d < %d): %H\n", e->dist, q->dist, e->o->hash);
- best = 1;
- }
- for(i = 0; i < q->nhead; i++)
- if(hasheq(&q->head[i], &e->o->hash)){
- dprint(1, "found best (exact head): %H\n", e->o->hash);
- best = 1;
- exact = 1;
- }
- for(i = 0; i < q->ntail; i++)
- if(hasheq(&q->tail[i], &e->o->hash)){
- dprint(1, "found best (exact tail): %H\n", e->o->hash);
- best = 1;
- exact = 1;
- }
- if(best){
- q->best = e->o;
- q->dist = e->dist;
- }
- return exact;
-}
-
-static int
-repaint(Lcaq *lcaq, Objset *keep, Objset *drop, Object *o, int dist, int ancestor)
-{
- Lcaq objq;
- Qelt e;
- Object *p;
- int i;
-
- qinit(&objq);
- if((o = readobject(o->hash)) == nil)
- return -1;
- qput(&objq, o, Drop, dist);
- while(qpop(&objq, &e)){
- o = e.o;
- if(oshas(drop, o->hash))
- continue;
- if(ancestor && pickbest(lcaq, &e, Keep))
- goto out;
- if(!oshas(keep, o->hash)){
- dprint(2, "repaint: blank => drop %H\n", o->hash);
- osadd(drop, o);
- continue;
- }
- for(i = 0; i < o->commit->nparent; i++){
- if(oshas(drop, o->commit->parent[i]))
- continue;
- if((p = readobject(o->commit->parent[i])) == nil)
- goto out;
- if(p->type != GCommit){
- fprint(2, "hash %H not commit\n", p->hash);
- unref(p);
- }
- qput(&objq, p, Drop, e.dist+1);
- }
- unref(e.o);
- }
-out:
- qclear(&objq);
- return 0;
-}
-
-static int
paint(Hash *head, int nhead, Hash *tail, int ntail, Object ***res, int *nres, int ancestor)
{
Qelt e;
- Lcaq objq;
- Objset keep, drop;
+ Objq objq;
+ Objset keep, drop, skip;
Object *o, *c;
- int i, ncolor;
+ int i, nskip;
osinit(&keep);
osinit(&drop);
- memset(&objq, 0, sizeof(objq));
+ osinit(&skip);
qinit(&objq);
- objq.head = head;
- objq.nhead = nhead;
- objq.tail = tail;
- objq.ntail = ntail;
- objq.dist = 1<<30;
+ nskip = 0;
for(i = 0; i < nhead; i++){
if((o = readobject(head[i])) == nil){
@@ 237,7 128,7 @@ paint(Hash *head, int nhead, Hash *tail, int ntail, Object ***res, int *nres, in
continue;
}
dprint(1, "init: keep %H\n", o->hash);
- qput(&objq, o, Keep, 0);
+ qput(&objq, o, Keep);
unref(o);
}
for(i = 0; i < ntail; i++){
@@ 251,70 142,83 @@ paint(Hash *head, int nhead, Hash *tail, int ntail, Object ***res, int *nres, in
continue;
}
dprint(1, "init: drop %H\n", o->hash);
- qput(&objq, o, Drop, 0);
+ qput(&objq, o, Drop);
unref(o);
}
dprint(1, "finding twixt commits\n");
- while(qpop(&objq, &e)){
- if(oshas(&drop, e.o->hash))
- ncolor = Drop;
- else if(oshas(&keep, e.o->hash))
- ncolor = Keep;
- else
- ncolor = Blank;
- if(ancestor && pickbest(&objq, &e, ncolor))
- goto exactlca;
- if(ncolor == Keep && e.color == Keep || ncolor == Drop)
+ while(nskip != objq.nheap && qpop(&objq, &e)){
+ if(e.color == Skip)
+ nskip--;
+ if(oshas(&skip, e.o->hash))
continue;
- if(ncolor == Keep && e.color == Drop){
- if(repaint(&objq, &keep, &drop, e.o, e.dist, ancestor) == -1)
+ switch(e.color){
+ case Keep:
+ if(oshas(&keep, e.o->hash))
+ continue;
+ if(oshas(&drop, e.o->hash))
+ e.color = Skip;
+ osadd(&keep, e.o);
+ break;
+ case Drop:
+ if(oshas(&drop, e.o->hash))
+ continue;
+ if(oshas(&keep, e.o->hash))
+ e.color = Skip;
+ osadd(&drop, e.o);
+ break;
+ case Skip:
+ osadd(&skip, e.o);
+ break;
+ }
+ o = readobject(e.o->hash);
+ for(i = 0; i < o->commit->nparent; i++){
+ if((c = readobject(e.o->commit->parent[i])) == nil)
goto error;
- }else if (ncolor == Blank) {
- if(e.color == Keep)
- osadd(&keep, e.o);
- else
- osadd(&drop, e.o);
- o = readobject(e.o->hash);
- for(i = 0; i < o->commit->nparent; i++){
- if((c = readobject(e.o->commit->parent[i])) == nil)
- goto error;
- if(c->type != GCommit){
- fprint(2, "warning: %H does not point at commit\n", c->hash);
- unref(c);
- continue;
- }
- dprint(2, "\tenqueue: %s %H\n", colors[e.color], c->hash);
- qput(&objq, c, e.color, e.dist+1);
+ if(c->type != GCommit){
+ fprint(2, "warning: %H does not point at commit\n", c->hash);
unref(c);
+ continue;
}
- unref(o);
+ dprint(2, "\tenqueue: %s %H\n", colors[e.color], c->hash);
+ qput(&objq, c, e.color);
+ unref(c);
+ if(e.color == Skip)
+ nskip++;
}
+ unref(o);
}
-exactlca:
if(ancestor){
dprint(1, "found ancestor\n");
- if(objq.best == nil){
+ o = nil;
+ for(i = 0; i < keep.sz; i++){
+ o = keep.obj[i];
+ if(o != nil && oshas(&drop, o->hash) && !oshas(&skip, o->hash))
+ break;
+ }
+ if(i == keep.sz){
*nres = 0;
*res = nil;
}else{
*nres = 1;
*res = eamalloc(1, sizeof(Object*));
- (*res)[0] = objq.best;
+ (*res)[0] = o;
}
}else{
dprint(1, "found twixt\n");
*res = eamalloc(keep.nobj, sizeof(Object*));
*nres = 0;
for(i = 0; i < keep.sz; i++){
- if(keep.obj[i] != nil && !oshas(&drop, keep.obj[i]->hash)){
- (*res)[*nres] = keep.obj[i];
+ o = keep.obj[i];
+ if(o != nil && !oshas(&drop, o->hash) && !oshas(&skip, o->hash)){
+ (*res)[*nres] = o;
(*nres)++;
}
}
}
osclear(&keep);
osclear(&drop);
+ osclear(&skip);
return 0;
error:
dprint(1, "twixt error: %r\n");
@@ 406,7 310,7 @@ static int
range(Eval *ev)
{
Object *a, *b, *p, *q, **all;
- int nall, *idx, mark;
+ int nall, *idx;
Objset keep, skip;
b = pop(ev);
@@ 424,7 328,6 @@ range(Eval *ev)
all = nil;
idx = nil;
nall = 0;
- mark = ev->nstk;
osinit(&keep);
osinit(&skip);
osadd(&keep, a);
@@ 459,7 362,6 @@ range(Eval *ev)
nall++;
}
free(all);
- qsort(ev->stk + mark, ev->nstk - mark, sizeof(Object*), objdatecmp);
return 0;
error:
free(all);
M revert => revert +3 -1
@@ 5,7 5,8 @@ rfork en
gitup
flagfmt='c:query query' args='file ...'
-eval `''{aux/getflags $*} || exec aux/usage
+if (! eval `''{aux/getflags $*} || ~ $#* 0)
+ exec aux/usage
commit=$gitfs/HEAD
if(~ $#query 1)
@@ 15,6 16,7 @@ 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
+ touch $f
git/add $f
}
exit ''
M send.c => send.c +10 -4
@@ 134,8 134,8 @@ sendpack(Conn *c)
nmap = nours;
map = eamalloc(nmap, sizeof(Map));
for(i = 0; i < nmap; i++){
- map[i].ours = ours[i];
map[i].theirs = Zhash;
+ map[i].ours = ours[i];
map[i].ref = refs[i];
}
while(1){
@@ 155,9 155,15 @@ sendpack(Conn *c)
theirs = earealloc(theirs, ntheirs+1, sizeof(Hash));
if(hparse(&theirs[ntheirs], sp[0]) == -1)
sysfatal("invalid hash %s", sp[0]);
+ if((idx = findkey(map, nmap, sp[1])) != -1)
+ map[idx].theirs = theirs[ntheirs];
+ /*
+ * we only keep their ref if we can read the object to add it
+ * to our reachability; otherwise, discard it; we only care
+ * that we don't have it, so we can tell whether we need to
+ * bail out of pushing.
+ */
if((o = readobject(theirs[ntheirs])) != nil){
- if((idx = findkey(map, nmap, sp[1])) != -1)
- map[idx].theirs = theirs[ntheirs];
ntheirs++;
unref(o);
}
@@ 180,7 186,7 @@ sendpack(Conn *c)
p = ancestor(a, b);
if(!force && !hasheq(&m->theirs, &Zhash) && (a == nil || p != a)){
fprint(2, "remote has diverged\n");
- werrstr("force needed");
+ werrstr("remote diverged");
flushpkt(c);
return -1;
}
M serve.c => serve.c +12 -11
@@ 362,7 362,7 @@ lockrepo(void)
int
updaterefs(Conn *c, Hash *cur, Hash *upd, char **ref, int nupd)
{
- char refpath[512];
+ char refpath[512], buf[128];
int i, newidx, hadref, fd, ret, lockfd;
vlong newtm;
Object *o;
@@ 378,19 378,19 @@ updaterefs(Conn *c, Hash *cur, Hash *upd, char **ref, int nupd)
*/
newtm = -23811206400;
if((lockfd = lockrepo()) == -1){
- werrstr("repo locked\n");
+ snprint(buf, sizeof(buf), "repo locked\n");
return -1;
}
for(i = 0; i < nupd; i++){
if(resolveref(&h, ref[i]) == 0){
hadref = 1;
if(!hasheq(&h, &cur[i])){
- werrstr("old ref changed: %s", ref[i]);
+ snprint(buf, sizeof(buf), "old ref changed: %s", ref[i]);
goto error;
}
}
if(snprint(refpath, sizeof(refpath), ".git/%s", ref[i]) == sizeof(refpath)){
- werrstr("ref path too long: %s", ref[i]);
+ snprint(buf, sizeof(buf), "ref path too long: %s", ref[i]);
goto error;
}
if(hasheq(&upd[i], &Zhash)){
@@ 398,11 398,11 @@ updaterefs(Conn *c, Hash *cur, Hash *upd, char **ref, int nupd)
continue;
}
if((o = readobject(upd[i])) == nil){
- werrstr("update to nonexistent hash %H", upd[i]);
+ snprint(buf, sizeof(buf), "update to nonexistent hash %H", upd[i]);
goto error;
}
if(o->type != GCommit){
- werrstr("not commit: %H", upd[i]);
+ snprint(buf, sizeof(buf), "not commit: %H", upd[i]);
goto error;
}
if(o->commit->mtime > newtm){
@@ 411,11 411,11 @@ updaterefs(Conn *c, Hash *cur, Hash *upd, char **ref, int nupd)
}
unref(o);
if((fd = create(refpath, OWRITE|OTRUNC, 0644)) == -1){
- werrstr("open ref: %r");
+ snprint(buf, sizeof(buf), "open ref: %r");
goto error;
}
if(fprint(fd, "%H", upd[i]) == -1){
- werrstr("upate ref: %r");
+ snprint(buf, sizeof(buf), "upate ref: %r");
close(fd);
goto error;
}
@@ 436,19 436,20 @@ updaterefs(Conn *c, Hash *cur, Hash *upd, char **ref, int nupd)
*/
if(resolveref(&h, "HEAD") == -1 && hadref == 0 && newidx != -1){
if((fd = create(".git/HEAD", OWRITE|OTRUNC, 0644)) == -1){
- werrstr("open HEAD: %r");
+ snprint(buf, sizeof(buf), "open HEAD: %r");
goto error;
}
if(fprint(fd, "ref: %s", ref[0]) == -1){
- werrstr("write HEAD ref: %r");
+ snprint(buf, sizeof(buf), "write HEAD ref: %r");
goto error;
}
close(fd);
}
ret = 0;
error:
- fmtpkt(c, "ERR %r");
+ fmtpkt(c, "ERR %s", buf);
close(lockfd);
+ werrstr(buf);
return ret;
}
M util.c => util.c +5 -6
@@ 338,7 338,7 @@ qclear(Objq *q)
}
void
-qput(Objq *q, Object *o, int color, int dist)
+qput(Objq *q, Object *o, int color)
{
Qelt t;
int i;
@@ 349,10 349,9 @@ qput(Objq *q, Object *o, int color, int dist)
}
q->heap[q->nheap].o = o;
q->heap[q->nheap].color = color;
- q->heap[q->nheap].dist = dist;
- q->heap[q->nheap].mtime = o->commit->mtime;
+ q->heap[q->nheap].ctime = o->commit->ctime;
for(i = q->nheap; i > 0; i = (i-1)/2){
- if(q->heap[i].mtime < q->heap[(i-1)/2].mtime)
+ if(q->heap[i].ctime < q->heap[(i-1)/2].ctime)
break;
t = q->heap[i];
q->heap[i] = q->heap[(i-1)/2];
@@ 379,9 378,9 @@ qpop(Objq *q, Qelt *e)
m = i;
l = 2*i+1;
r = 2*i+2;
- if(l < q->nheap && q->heap[m].mtime < q->heap[l].mtime)
+ if(l < q->nheap && q->heap[m].ctime < q->heap[l].ctime)
m = l;
- if(r < q->nheap && q->heap[m].mtime < q->heap[r].mtime)
+ if(r < q->nheap && q->heap[m].ctime < q->heap[r].ctime)
m = r;
if(m == i)
break;
M walk.c => walk.c +3 -15
@@ 30,7 30,6 @@ enum {
Cache seencache[NCACHE];
int quiet;
int printflg;
-char *base;
char *rstr = "R ";
char *tstr = "T ";
char *mstr = "M ";
@@ 210,21 209,19 @@ mismatch:
void
usage(void)
{
- fprint(2, "usage: %s [-qbc] [-f filt] [-b base] [paths...]\n", argv0);
+ fprint(2, "usage: %s [-qbc] [-f filt] [paths...]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
- char *rpath, *tpath, *bpath, *cpath, buf[8], repo[512];
+ char *rpath, *tpath, *bpath, buf[8], repo[512];
char *p, *e;
int i, dirty;
- Hash h;
Wres r;
Dir *d;
-;
ARGBEGIN{
case 'q':
quiet++;
@@ 245,9 242,6 @@ main(int argc, char **argv)
default: usage(); break;
}
break;
- case 'b':
- base = EARGF(usage());
- break;
default:
usage();
}ARGEND
@@ 258,12 252,6 @@ main(int argc, char **argv)
sysfatal("chdir: %r");
if(access(".git/fs/ctl", AEXIST) != 0)
sysfatal("no running git/fs");
- cpath = HDIR;
- if(base != nil){
- if(resolveref(&h, base) == -1)
- sysfatal("invalid base commit %s", base);
- cpath = smprint(".git/fs/object/%H/tree", h);
- }
dirty = 0;
memset(&r, 0, sizeof(r));
if(printflg == 0)
@@ 301,7 289,7 @@ nextarg:
goto next;
rpath = smprint(RDIR"/%s", p);
tpath = smprint(TDIR"/%s", p);
- bpath = smprint("%s/%s", cpath, p);
+ bpath = smprint(HDIR"/%s", p);
/* Fast path: we don't want to force access to the rpath. */
if(d && sameqid(d, tpath)) {
if(!quiet && (printflg & Tflg))