#include <bio.h>
#include <mp.h>
#include <libsec.h>
#include <flate.h>
#include <regexp.h>
typedef struct Capset Capset;
typedef struct Conn Conn;
typedef struct Hash Hash;
typedef struct Delta Delta;
typedef struct Cinfo Cinfo;
typedef struct Tinfo Tinfo;
typedef struct Object Object;
typedef struct Objset Objset;
typedef struct Pack Pack;
typedef struct Buf Buf;
typedef struct Dirent Dirent;
typedef struct Idxent Idxent;
typedef struct Objlist Objlist;
typedef struct Dtab Dtab;
typedef struct Dblock Dblock;
typedef struct Objq Objq;
typedef struct Qelt Qelt;
enum {
Pathmax = 512,
Npackcache = 32,
Hashsz = 20,
Pktmax = 65536,
KiB = 1024,
MiB = 1024*KiB,
};
enum {
GNone = 0,
GCommit = 1,
GTree = 2,
GBlob = 3,
GTag = 4,
GOdelta = 6,
GRdelta = 7,
};
enum {
Cloaded = 1 << 0,
Cidx = 1 << 1,
Ccache = 1 << 2,
Cexist = 1 << 3,
Cparsed = 1 << 5,
Cthin = 1 << 6,
};
enum {
ConnGit,
ConnGit9,
ConnSsh,
ConnHttp,
};
struct Objlist {
int idx;
int fd;
int state;
int stage;
Dir *top;
int ntop;
int topidx;
Dir *loose;
int nloose;
int looseidx;
Dir *pack;
int npack;
int packidx;
int nent;
int entidx;
};
struct Hash {
uchar h[20];
};
struct Conn {
int type;
int rfd;
int wfd;
/* only used by http */
int cfd;
char *url; /* note, first GET uses a different url */
char *dir;
char *direction;
};
struct Dirent {
char *name;
int mode;
Hash h;
char ismod;
char islink;
};
struct Object {
/* Git data */
Hash hash;
int type;
/* Cache */
int id;
int flag;
int refs;
Object *next;
Object *prev;
/* For indexing */
vlong off;
vlong len;
u32int crc;
/* Everything below here gets cleared */
char *all;
char *data;
/* size excludes header */
vlong size;
/* Significant win on memory use */
union {
Cinfo *commit;
Tinfo *tree;
};
};
struct Tinfo {
/* Tree */
Dirent *ent;
int nent;
};
struct Cinfo {
/* Commit */
Hash *parent;
int nparent;
Hash tree;
char *author;
char *committer;
char *msg;
int nmsg;
vlong ctime;
vlong mtime;
};
struct Objset {
Object **obj;
int nobj;
int sz;
};
struct Qelt {
Object *o;
vlong ctime;
int color;
};
struct Objq {
Qelt *heap;
int nheap;
int heapsz;
};
struct Dtab {
Object *o;
uchar *base;
int nbase;
Dblock *b;
int nb;
int sz;
};
struct Dblock {
uchar *buf;
int len;
int off;
u64int hash;
};
struct Delta {
int cpy;
int off;
int len;
};
#define GETBE16(b)\
((((b)[0] & 0xFFul) << 8) | \
(((b)[1] & 0xFFul) << 0))
#define GETBE32(b)\
((((b)[0] & 0xFFul) << 24) | \
(((b)[1] & 0xFFul) << 16) | \
(((b)[2] & 0xFFul) << 8) | \
(((b)[3] & 0xFFul) << 0))
#define GETBE64(b)\
((((b)[0] & 0xFFull) << 56) | \
(((b)[1] & 0xFFull) << 48) | \
(((b)[2] & 0xFFull) << 40) | \
(((b)[3] & 0xFFull) << 32) | \
(((b)[4] & 0xFFull) << 24) | \
(((b)[5] & 0xFFull) << 16) | \
(((b)[6] & 0xFFull) << 8) | \
(((b)[7] & 0xFFull) << 0))
#define PUTBE16(b, n)\
do{ \
(b)[0] = (n) >> 8; \
(b)[1] = (n) >> 0; \
} while(0)
#define PUTBE32(b, n)\
do{ \
(b)[0] = (n) >> 24; \
(b)[1] = (n) >> 16; \
(b)[2] = (n) >> 8; \
(b)[3] = (n) >> 0; \
} while(0)
#define PUTBE64(b, n)\
do{ \
(b)[0] = (n) >> 56; \
(b)[1] = (n) >> 48; \
(b)[2] = (n) >> 40; \
(b)[3] = (n) >> 32; \
(b)[4] = (n) >> 24; \
(b)[5] = (n) >> 16; \
(b)[6] = (n) >> 8; \
(b)[7] = (n) >> 0; \
} while(0)
#define QDIR(qid) ((int)(qid)->path & (0xff))
#define isblank(c) \
(((c) != '\n') && isspace(c))
extern Reprog *authorpat;
extern Objset objcache;
extern vlong cachemax;
extern Hash Zhash;
extern int chattygit;
extern int interactive;
#pragma varargck type "H" Hash
#pragma varargck type "T" int
#pragma varargck type "O" Object*
#pragma varargck type "Q" Qid
int Hfmt(Fmt*);
int Tfmt(Fmt*);
int Ofmt(Fmt*);
int Qfmt(Fmt*);
void gitinit(void);
/* object io */
int resolverefs(Hash **, char *);
int resolveref(Hash *, char *);
int listrefs(Hash **, char ***);
Object *ancestor(Object *, Object *);
int findtwixt(Hash *, int, Hash *, int, Object ***, int *);
Object *readobject(Hash);
Object *clearedobject(Hash, int);
void parseobject(Object *);
int indexpack(char *, char *, Hash);
int writepack(int, Hash*, int, Hash*, int, Hash*);
int hasheq(Hash *, Hash *);
Object *ref(Object *);
void unref(Object *);
void cache(Object *);
Object *emptydir(void);
/* object sets */
void osinit(Objset *);
void osclear(Objset *);
void osadd(Objset *, Object *);
int oshas(Objset *, Hash);
Object *osfind(Objset *, Hash);
/* object listing */
Objlist *mkols(void);
int olsnext(Objlist *, Hash *);
void olsfree(Objlist *);
/* util functions */
#define dprint(lvl, ...) \
if(chattygit >= lvl) _dprint(__VA_ARGS__)
void _dprint(char *, ...);
void *eamalloc(ulong, ulong);
void *emalloc(ulong);
void *earealloc(void *, ulong, ulong);
void *erealloc(void *, ulong);
char *estrdup(char *);
int slurpdir(char *, Dir **);
int hparse(Hash *, char *);
int hassuffix(char *, char *);
int swapsuffix(char *, int, char *, char *, char *);
char *strip(char *);
int findrepo(char *, int);
int showprogress(int, int);
u64int murmurhash2(void*, usize);
/* packing */
void dtinit(Dtab *, Object*);
void dtclear(Dtab*);
Delta* deltify(Object*, Dtab*, int*);
/* proto handling */
int readpkt(Conn*, char*, int);
int writepkt(Conn*, char*, int);
int fmtpkt(Conn*, char*, ...);
int flushpkt(Conn*);
void initconn(Conn*, int, int);
int gitconnect(Conn *, char *, char *);
int readphase(Conn *);
int writephase(Conn *);
void closeconn(Conn *);
/* queues */
void qinit(Objq*);
void qclear(Objq*);
void qput(Objq*, Object*, int);
int qpop(Objq*, Qelt*);
/* in 9front but not in 9legacy */
Biobuf* Bfdopen(int, int);
|