Ori Bernsteingit: got git?da254e55 years agoHistory
170 lines · 2.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <ctype.h>#include "git.h" enum {	Sinit,	Siter,}; static intcrackidx(char *path, int *np){	int fd;	char buf[4]; 	if((fd = open(path, OREAD)) == -1)		return -1;	if(seek(fd, 8 + 255*4, 0) == -1)		return -1;	if(readn(fd, buf, sizeof(buf)) != sizeof(buf))		return -1;	*np = GETBE32(buf);	return fd;} intisloosedir(char *s){	return strlen(s) == 2 && isxdigit(s[0]) && isxdigit(s[1]);} intendswith(char *n, char *s){	int nn, ns; 	nn = strlen(n);	ns = strlen(s);	return nn > ns && strcmp(n + nn - ns, s) == 0;} intolsreadpacked(Objlist *ols, Hash *h){	char *p;	int i, j; 	i = ols->packidx;	j = ols->entidx; 	if(ols->state == Siter)		goto step;	for(i = 0; i < ols->npack; i++){		if(!endswith(ols->pack[i].name, ".idx"))			continue;		if((p = smprint(".git/objects/pack/%s", ols->pack[i].name)) == nil)			sysfatal("smprint: %r");		ols->fd = crackidx(p, &ols->nent);		free(p);		if(ols->fd == -1)			continue;		j = 0;		while(j < ols->nent){			if(readn(ols->fd, h->h, sizeof(h->h)) != sizeof(h->h))				continue;			ols->state = Siter;			ols->packidx = i;			ols->entidx = j;			return 0;step:			j++;		}		close(ols->fd);	}	ols->state = Sinit;	return -1;}  intolsreadloose(Objlist *ols, Hash *h){	char buf[64], *p;	int i, j, n; 	i = ols->topidx;	j = ols->looseidx;	if(ols->state == Siter)		goto step;	for(i = 0; i < ols->ntop; i++){		if(!isloosedir(ols->top[i].name))			continue;		if((p = smprint(".git/objects/%s", ols->top[i].name)) == nil)			sysfatal("smprint: %r");		ols->fd = open(p, OREAD);		free(p);		if(ols->fd == -1)			continue;		while((ols->nloose = dirread(ols->fd, &ols->loose)) > 0){			j = 0;			while(j < ols->nloose){				n = snprint(buf, sizeof(buf), "%s%s", ols->top[i].name, ols->loose[j].name);				if(n >= sizeof(buf))					goto step;				if(hparse(h, buf) == -1)					goto step;				ols->state = Siter;				ols->topidx = i;				ols->looseidx = j;				return 0;step:				j++;			}			free(ols->loose);			ols->loose = nil;		}		close(ols->fd);		ols->fd = -1;	}	ols->state = Sinit;	return -1;} Objlist*mkols(void){	Objlist *ols; 	ols = emalloc(sizeof(Objlist));	if((ols->ntop = slurpdir(".git/objects", &ols->top)) == -1)		sysfatal("read top level: %r");	if((ols->npack = slurpdir(".git/objects/pack", &ols->pack)) == -1)		ols->pack = nil;	ols->fd = -1;	return ols;} voidolsfree(Objlist *ols){	if(ols == nil)		return;	if(ols->fd != -1)		close(ols->fd);	free(ols->top);	free(ols->loose);	free(ols->pack);	free(ols);} intolsnext(Objlist *ols, Hash *h){	if(ols->stage == 0){		if(olsreadloose(ols, h) != -1){			ols->idx++;			return 0;		}		ols->stage++;	}	if(ols->stage == 1){		if(olsreadpacked(ols, h) != -1){			ols->idx++;			return 0;		}		ols->stage++;	}	return -1;}