git/send: pick minimal delta set correctly (thanks igor)

We weren't giving all objects to the twixt() function, and
it was making bad life choices -- gambling, smoking, drinking,
and packing in too much data.

With more information, it doesn't do the last.
This commit is contained in:
Ori Bernstein 2021-05-31 18:02:23 -07:00
parent c297482269
commit 1160919f81
3 changed files with 51 additions and 19 deletions

View file

@ -1326,7 +1326,7 @@ loadtree(Metavec *v, Objset *has, Hash tree, char *dpath, vlong mtime)
if(t->type != GTree){ if(t->type != GTree){
fprint(2, "load: %H: not tree\n", t->hash); fprint(2, "load: %H: not tree\n", t->hash);
unref(t); unref(t);
return -1; return 0;
} }
addmeta(v, has, t, dpath, mtime); addmeta(v, has, t, dpath, mtime);
for(i = 0; i < t->tree->nent; i++){ for(i = 0; i < t->tree->nent; i++){
@ -1363,7 +1363,7 @@ loadcommit(Metavec *v, Objset *has, Hash h)
if(c->type != GCommit){ if(c->type != GCommit){
fprint(2, "load: %H: not commit\n", c->hash); fprint(2, "load: %H: not commit\n", c->hash);
unref(c); unref(c);
return -1; return 0;
} }
addmeta(v, has, c, "", c->commit->ctime); addmeta(v, has, c, "", c->commit->ctime);
r = loadtree(v, has, c->commit->tree, "", c->commit->ctime); r = loadtree(v, has, c->commit->tree, "", c->commit->ctime);

View file

@ -294,11 +294,11 @@ findtwixt(Hash *head, int nhead, Hash *tail, int ntail, Object ***res, int *nres
if(hasheq(&tail[i], &Zhash)) if(hasheq(&tail[i], &Zhash))
continue; continue;
if((o = readobject(tail[i])) == nil){ if((o = readobject(tail[i])) == nil){
fprint(2, "warning: %H does not point at commit\n", o->hash);
werrstr("read tail %H: %r", tail[i]); werrstr("read tail %H: %r", tail[i]);
return -1; return -1;
} }
if(o->type != GCommit){ if(o->type != GCommit){
fprint(2, "warning: %H does not point at commit\n", o->hash);
unref(o); unref(o);
continue; continue;
} }

View file

@ -4,6 +4,7 @@
#include "git.h" #include "git.h"
typedef struct Capset Capset; typedef struct Capset Capset;
typedef struct Map Map;
struct Capset { struct Capset {
int sideband; int sideband;
@ -11,6 +12,12 @@ struct Capset {
int report; int report;
}; };
struct Map {
char *ref;
Hash ours;
Hash theirs;
};
int sendall; int sendall;
int force; int force;
int nbranch; int nbranch;
@ -24,13 +31,22 @@ int
findref(char **r, int nr, char *ref) findref(char **r, int nr, char *ref)
{ {
int i; int i;
for(i = 0; i < nr; i++) for(i = 0; i < nr; i++)
if(strcmp(r[i], ref) == 0) if(strcmp(r[i], ref) == 0)
return i; return i;
return -1; return -1;
} }
int
findkey(Map *m, int nm, char *ref)
{
int i;
for(i = 0; i < nm; i++)
if(strcmp(m[i].ref, ref) == 0)
return i;
return -1;
}
int int
readours(Hash **tailp, char ***refp) readours(Hash **tailp, char ***refp)
{ {
@ -101,17 +117,27 @@ parsecaps(char *caps, Capset *cs)
int int
sendpack(Conn *c) sendpack(Conn *c)
{ {
int i, n, idx, nupd, nsp, send, first; int i, n, idx, nsp, send, first;
int nours, ntheirs, nmap;
char buf[Pktmax], *sp[3]; char buf[Pktmax], *sp[3];
Hash h, *theirs, *ours; Hash h, *theirs, *ours;
Object *a, *b, *p; Object *a, *b, *p;
char **refs; char **refs;
Capset cs; Capset cs;
Map *map, *m;
first = 1; first = 1;
memset(&cs, 0, sizeof(Capset)); memset(&cs, 0, sizeof(Capset));
nupd = readours(&ours, &refs); nours = readours(&ours, &refs);
theirs = eamalloc(nupd, sizeof(Hash)); theirs = nil;
ntheirs = 0;
nmap = nours;
map = eamalloc(nmap, sizeof(Map));
for(i = 0; i < nmap; i++){
map[i].ours = ours[i];
map[i].theirs = Zhash;
map[i].ref = refs[i];
}
while(1){ while(1){
n = readpkt(c, buf, sizeof(buf)); n = readpkt(c, buf, sizeof(buf));
if(n == -1) if(n == -1)
@ -126,10 +152,12 @@ sendpack(Conn *c)
if(getfields(buf, sp, nelem(sp), 1, " \t\r\n") != 2) if(getfields(buf, sp, nelem(sp), 1, " \t\r\n") != 2)
sysfatal("invalid ref line %.*s", utfnlen(buf, n), buf); sysfatal("invalid ref line %.*s", utfnlen(buf, n), buf);
if((idx = findref(refs, nupd, sp[1])) == -1) theirs = earealloc(theirs, ntheirs+1, sizeof(Hash));
continue; if(hparse(&theirs[ntheirs], sp[0]) == -1)
if(hparse(&theirs[idx], sp[0]) == -1)
sysfatal("invalid hash %s", sp[0]); sysfatal("invalid hash %s", sp[0]);
if((idx = findkey(map, nmap, sp[1])) != -1)
map[idx].theirs = theirs[ntheirs];
ntheirs++;
} }
if(writephase(c) == -1) if(writephase(c) == -1)
@ -137,13 +165,17 @@ sendpack(Conn *c)
send = 0; send = 0;
if(force) if(force)
send=1; send=1;
for(i = 0; i < nupd; i++){ for(i = 0; i < nmap; i++){
a = readobject(theirs[i]); m = &map[i];
b = hasheq(&ours[i], &Zhash) ? nil : readobject(ours[i]); a = readobject(m->theirs);
if(hasheq(&m->ours, &Zhash))
b = nil;
else
b = readobject(m->ours);
p = nil; p = nil;
if(a != nil && b != nil) if(a != nil && b != nil)
p = ancestor(a, b); p = ancestor(a, b);
if(!force && !hasheq(&theirs[i], &Zhash) && (a == nil || p != a)){ if(!force && !hasheq(&m->theirs, &Zhash) && (a == nil || p != a)){
fprint(2, "remote has diverged\n"); fprint(2, "remote has diverged\n");
werrstr("force needed"); werrstr("force needed");
flushpkt(c); flushpkt(c);
@ -152,12 +184,12 @@ sendpack(Conn *c)
unref(a); unref(a);
unref(b); unref(b);
unref(p); unref(p);
if(hasheq(&theirs[i], &ours[i])){ if(hasheq(&m->theirs, &m->ours)){
print("uptodate %s\n", refs[i]); print("uptodate %s\n", m->ref);
continue; continue;
} }
print("update %s %H %H\n", refs[i], theirs[i], ours[i]); print("update %s %H %H\n", m->ref, m->theirs, m->ours);
n = snprint(buf, sizeof(buf), "%H %H %s", theirs[i], ours[i], refs[i]); n = snprint(buf, sizeof(buf), "%H %H %s", m->theirs, m->ours, m->ref);
/* /*
* Workaround for github. * Workaround for github.
@ -183,7 +215,7 @@ sendpack(Conn *c)
return 0; return 0;
} }
if(writepack(c->wfd, ours, nupd, theirs, nupd, &h) == -1) if(writepack(c->wfd, ours, nours, theirs, ntheirs, &h) == -1)
return -1; return -1;
if(!cs.report) if(!cs.report)
return 0; return 0;