1*cf5a6c84SAndroid Build Coastguard Worker /* git.c - A minimal git clone
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2022 Moritz C. Weber <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See https://git-scm.com/docs/git-init
6*cf5a6c84SAndroid Build Coastguard Worker * https://git-scm.com/docs/git-remote
7*cf5a6c84SAndroid Build Coastguard Worker * https://git-scm.com/docs/git-fetch
8*cf5a6c84SAndroid Build Coastguard Worker * https://git-scm.com/docs/git-checkout
9*cf5a6c84SAndroid Build Coastguard Worker * https://git-scm.com/docs/pack-format
10*cf5a6c84SAndroid Build Coastguard Worker * https://git-scm.com/docs/index-format
11*cf5a6c84SAndroid Build Coastguard Worker * https://www.alibabacloud.com/blog/a-detailed-explanation-of-the-underlying-data-structures-and-principles-of-git_597391
12*cf5a6c84SAndroid Build Coastguard Worker * https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt
13*cf5a6c84SAndroid Build Coastguard Worker * https://stackoverflow.com/a/14303988
14*cf5a6c84SAndroid Build Coastguard Worker * https://stackoverflow.com/a/21599232
15*cf5a6c84SAndroid Build Coastguard Worker * https://github.com/tarruda/node-git-core/blob/master/src/js/delta.js
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker
18*cf5a6c84SAndroid Build Coastguard Worker USE_GITCLONE(NEWTOY(gitclone, "<1", TOYFLAG_USR|TOYFLAG_BIN))
19*cf5a6c84SAndroid Build Coastguard Worker USE_GITINIT(NEWTOY(gitinit, "<1", TOYFLAG_USR|TOYFLAG_BIN))
20*cf5a6c84SAndroid Build Coastguard Worker USE_GITREMOTE(NEWTOY(gitremote, "<1", TOYFLAG_USR|TOYFLAG_BIN))
21*cf5a6c84SAndroid Build Coastguard Worker USE_GITFETCH(NEWTOY(gitfetch, 0, TOYFLAG_USR|TOYFLAG_BIN))
22*cf5a6c84SAndroid Build Coastguard Worker USE_GITCHECKOUT(NEWTOY(gitcheckout, "<1", TOYFLAG_USR|TOYFLAG_BIN))
23*cf5a6c84SAndroid Build Coastguard Worker
24*cf5a6c84SAndroid Build Coastguard Worker config GITCOMPAT
25*cf5a6c84SAndroid Build Coastguard Worker bool "gitcompat"
26*cf5a6c84SAndroid Build Coastguard Worker default n
27*cf5a6c84SAndroid Build Coastguard Worker help
28*cf5a6c84SAndroid Build Coastguard Worker Enable git compatible repos instead of minimal clone downloader.
29*cf5a6c84SAndroid Build Coastguard Worker
30*cf5a6c84SAndroid Build Coastguard Worker config GITCLONE
31*cf5a6c84SAndroid Build Coastguard Worker bool "gitclone"
32*cf5a6c84SAndroid Build Coastguard Worker default n
33*cf5a6c84SAndroid Build Coastguard Worker help
34*cf5a6c84SAndroid Build Coastguard Worker usage: gitclone URL
35*cf5a6c84SAndroid Build Coastguard Worker A minimal git clone.
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker config GITINIT
38*cf5a6c84SAndroid Build Coastguard Worker bool "gitinit"
39*cf5a6c84SAndroid Build Coastguard Worker default n
40*cf5a6c84SAndroid Build Coastguard Worker help
41*cf5a6c84SAndroid Build Coastguard Worker usage: gitinit NAME
42*cf5a6c84SAndroid Build Coastguard Worker A minimal git init.
43*cf5a6c84SAndroid Build Coastguard Worker
44*cf5a6c84SAndroid Build Coastguard Worker config GITREMOTE
45*cf5a6c84SAndroid Build Coastguard Worker bool "gitremote"
46*cf5a6c84SAndroid Build Coastguard Worker default n
47*cf5a6c84SAndroid Build Coastguard Worker help
48*cf5a6c84SAndroid Build Coastguard Worker usage: gitremote URL
49*cf5a6c84SAndroid Build Coastguard Worker A minimal git remote add origin.
50*cf5a6c84SAndroid Build Coastguard Worker
51*cf5a6c84SAndroid Build Coastguard Worker config GITFETCH
52*cf5a6c84SAndroid Build Coastguard Worker bool "gitfetch"
53*cf5a6c84SAndroid Build Coastguard Worker default n
54*cf5a6c84SAndroid Build Coastguard Worker help
55*cf5a6c84SAndroid Build Coastguard Worker usage: gitfetch
56*cf5a6c84SAndroid Build Coastguard Worker A minimal git fetch.
57*cf5a6c84SAndroid Build Coastguard Worker
58*cf5a6c84SAndroid Build Coastguard Worker config GITCHECKOUT
59*cf5a6c84SAndroid Build Coastguard Worker bool "gitcheckout"
60*cf5a6c84SAndroid Build Coastguard Worker default n
61*cf5a6c84SAndroid Build Coastguard Worker help
62*cf5a6c84SAndroid Build Coastguard Worker usage: gitcheckout <branch>
63*cf5a6c84SAndroid Build Coastguard Worker A minimal git checkout.
64*cf5a6c84SAndroid Build Coastguard Worker */
65*cf5a6c84SAndroid Build Coastguard Worker
66*cf5a6c84SAndroid Build Coastguard Worker #define FOR_gitclone
67*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
68*cf5a6c84SAndroid Build Coastguard Worker #include "openssl/sha.h" //ToDo: borrowed from OpenSSL to not pipe or refactor the SHA1SUM in toybox
69*cf5a6c84SAndroid Build Coastguard Worker #include "zlib.h" //ToDo: borrowed from libz to not refactor deflate.c
70*cf5a6c84SAndroid Build Coastguard Worker
71*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
72*cf5a6c84SAndroid Build Coastguard Worker char *url, *name; //git repo remote url and init directory name
73*cf5a6c84SAndroid Build Coastguard Worker struct IndexV2 *i; //git creates a index for each pack file, git clone just needs one index for the received pack file
74*cf5a6c84SAndroid Build Coastguard Worker )
75*cf5a6c84SAndroid Build Coastguard Worker
76*cf5a6c84SAndroid Build Coastguard Worker //git index format v2 described at https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L266
77*cf5a6c84SAndroid Build Coastguard Worker struct IndexV2 {
78*cf5a6c84SAndroid Build Coastguard Worker char header[8];// Git 4 byte magic number and 4 byte version number
79*cf5a6c84SAndroid Build Coastguard Worker unsigned fot[256];//A fan-out table
80*cf5a6c84SAndroid Build Coastguard Worker char (*sha1)[20];//Table of sorted object names(SHA1 hashes)
81*cf5a6c84SAndroid Build Coastguard Worker unsigned *crc, *offset;//Table of 4-bit CRC32 values and object offsets in pack file
82*cf5a6c84SAndroid Build Coastguard Worker long long *offset64; //8 byte offests -- not supported yet
83*cf5a6c84SAndroid Build Coastguard Worker char packsha1[20], idxsha1[20];//SHA1 hash of pack file and SHA1 hash of index file
84*cf5a6c84SAndroid Build Coastguard Worker };
85*cf5a6c84SAndroid Build Coastguard Worker
86*cf5a6c84SAndroid Build Coastguard Worker //TODO:This function is not used before git clone persists an index V2
read_index(struct IndexV2 * i)87*cf5a6c84SAndroid Build Coastguard Worker static void read_index(struct IndexV2 *i)
88*cf5a6c84SAndroid Build Coastguard Worker {
89*cf5a6c84SAndroid Build Coastguard Worker FILE *fpi;
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker i = xmalloc(sizeof(i));
92*cf5a6c84SAndroid Build Coastguard Worker i->sha1 = malloc(20);
93*cf5a6c84SAndroid Build Coastguard Worker i->crc = malloc(sizeof(unsigned));
94*cf5a6c84SAndroid Build Coastguard Worker i->offset = malloc(sizeof(unsigned));
95*cf5a6c84SAndroid Build Coastguard Worker i->offset64 = malloc(sizeof(long long));
96*cf5a6c84SAndroid Build Coastguard Worker //TODO: not used yet as index is not persisted yet
97*cf5a6c84SAndroid Build Coastguard Worker if (access(".git/object/pack/temp.idx", F_OK)==0) {
98*cf5a6c84SAndroid Build Coastguard Worker //persistance needed for other git commands (not clone)
99*cf5a6c84SAndroid Build Coastguard Worker fpi = fopen(".git/object/pack/temp.idx", "rb");
100*cf5a6c84SAndroid Build Coastguard Worker printf("read header\n");
101*cf5a6c84SAndroid Build Coastguard Worker fread(i->header, sizeof(i->header), 1, fpi);
102*cf5a6c84SAndroid Build Coastguard Worker printf("Header: %s..Read fot\n", i->header);
103*cf5a6c84SAndroid Build Coastguard Worker fread(i->fot, 4, 256, fpi);
104*cf5a6c84SAndroid Build Coastguard Worker printf("Elements %d..Read sha1\n", i->fot[255]);
105*cf5a6c84SAndroid Build Coastguard Worker fread(i->sha1, sizeof(i->fot), i->fot[255], fpi);
106*cf5a6c84SAndroid Build Coastguard Worker printf("read crc\n");
107*cf5a6c84SAndroid Build Coastguard Worker fread(i->crc, sizeof(i->fot), i->fot[255], fpi);
108*cf5a6c84SAndroid Build Coastguard Worker printf("read offset\n");
109*cf5a6c84SAndroid Build Coastguard Worker fread(i->offset, sizeof(i->fot), i->fot[255], fpi);
110*cf5a6c84SAndroid Build Coastguard Worker //TODO: Offsets for file size 2G missing here
111*cf5a6c84SAndroid Build Coastguard Worker printf("read packsha\n");
112*cf5a6c84SAndroid Build Coastguard Worker fread(i->packsha1, 20, 1, fpi);
113*cf5a6c84SAndroid Build Coastguard Worker printf("read idxsha\n");
114*cf5a6c84SAndroid Build Coastguard Worker fread(i->idxsha1, 20, 1, fpi);
115*cf5a6c84SAndroid Build Coastguard Worker fclose(fpi);
116*cf5a6c84SAndroid Build Coastguard Worker }
117*cf5a6c84SAndroid Build Coastguard Worker }
118*cf5a6c84SAndroid Build Coastguard Worker
bsearchpos(const char * k,const char * a,size_t h,size_t w)119*cf5a6c84SAndroid Build Coastguard Worker long bsearchpos(const char *k, const char *a, size_t h, size_t w)
120*cf5a6c84SAndroid Build Coastguard Worker {
121*cf5a6c84SAndroid Build Coastguard Worker long l = 0, m = 0, r = 0;
122*cf5a6c84SAndroid Build Coastguard Worker
123*cf5a6c84SAndroid Build Coastguard Worker if (!h) return 0;
124*cf5a6c84SAndroid Build Coastguard Worker while (h>0) {
125*cf5a6c84SAndroid Build Coastguard Worker m = l+(h/2);
126*cf5a6c84SAndroid Build Coastguard Worker r = strncmp(k, a+(m*w), 20);
127*cf5a6c84SAndroid Build Coastguard Worker if (!r||h==1) break; //match on search or position for insert
128*cf5a6c84SAndroid Build Coastguard Worker if (r<0) { h /= 2; } else { l = m; h -= h/2; }
129*cf5a6c84SAndroid Build Coastguard Worker }
130*cf5a6c84SAndroid Build Coastguard Worker
131*cf5a6c84SAndroid Build Coastguard Worker //For inserts check if insert is bigger obj at identified position
132*cf5a6c84SAndroid Build Coastguard Worker return m += (r>0) ? 1 : 0;
133*cf5a6c84SAndroid Build Coastguard Worker }
134*cf5a6c84SAndroid Build Coastguard Worker
135*cf5a6c84SAndroid Build Coastguard Worker //find offset position in packfile for given SHA1 hash
get_index(struct IndexV2 * i,char * h)136*cf5a6c84SAndroid Build Coastguard Worker long get_index(struct IndexV2 *i, char *h)
137*cf5a6c84SAndroid Build Coastguard Worker {
138*cf5a6c84SAndroid Build Coastguard Worker long pos = bsearchpos(h, i->sha1[0], i->fot[255], 20);
139*cf5a6c84SAndroid Build Coastguard Worker return i->offset[pos];
140*cf5a6c84SAndroid Build Coastguard Worker }
141*cf5a6c84SAndroid Build Coastguard Worker
142*cf5a6c84SAndroid Build Coastguard Worker //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L35
143*cf5a6c84SAndroid Build Coastguard Worker //https://yqintl.alicdn.com/eef7fe4f22cc97912cee011c99d3fe5821ae9e88.png
144*cf5a6c84SAndroid Build Coastguard Worker //read type and length of an packed object at a given offset
unpack(FILE * fpp,int * type,long * offset)145*cf5a6c84SAndroid Build Coastguard Worker unsigned long long unpack(FILE *fpp, int *type, long *offset)
146*cf5a6c84SAndroid Build Coastguard Worker {
147*cf5a6c84SAndroid Build Coastguard Worker int bitshift= 4;
148*cf5a6c84SAndroid Build Coastguard Worker unsigned long long length = 0;
149*cf5a6c84SAndroid Build Coastguard Worker char data;
150*cf5a6c84SAndroid Build Coastguard Worker
151*cf5a6c84SAndroid Build Coastguard Worker printf("Start unpack\n");
152*cf5a6c84SAndroid Build Coastguard Worker fseek(fpp, *offset, SEEK_SET);
153*cf5a6c84SAndroid Build Coastguard Worker printf("Offset set to: %ld\n", *offset);
154*cf5a6c84SAndroid Build Coastguard Worker fread(&data, 1, 1, fpp);
155*cf5a6c84SAndroid Build Coastguard Worker printf("Data: %d\n", data);
156*cf5a6c84SAndroid Build Coastguard Worker *type = ((data & 0x70)>>4);
157*cf5a6c84SAndroid Build Coastguard Worker printf("Type: %d\n", *type);
158*cf5a6c84SAndroid Build Coastguard Worker length |= data & 0x0F;
159*cf5a6c84SAndroid Build Coastguard Worker while ((data & 0x80) && fread(&data, 1, 1, fpp)!=-1)
160*cf5a6c84SAndroid Build Coastguard Worker {
161*cf5a6c84SAndroid Build Coastguard Worker length |= (unsigned long long)(data & 0x7F) << bitshift;
162*cf5a6c84SAndroid Build Coastguard Worker bitshift += 7; // (*offset)++;
163*cf5a6c84SAndroid Build Coastguard Worker }
164*cf5a6c84SAndroid Build Coastguard Worker printf("Length: %llu\n", length);
165*cf5a6c84SAndroid Build Coastguard Worker
166*cf5a6c84SAndroid Build Coastguard Worker return length;
167*cf5a6c84SAndroid Build Coastguard Worker }
168*cf5a6c84SAndroid Build Coastguard Worker
169*cf5a6c84SAndroid Build Coastguard Worker // ToDo: borrowed from int inf(FILE *source, FILE *dest) in
170*cf5a6c84SAndroid Build Coastguard Worker // zpipe.c: example of proper use of zlib's inflate() and deflate()
171*cf5a6c84SAndroid Build Coastguard Worker // Not copyrighted -- provided to the public domain
172*cf5a6c84SAndroid Build Coastguard Worker // Version 1.4 11 December 2005 Mark Adler */
173*cf5a6c84SAndroid Build Coastguard Worker #define CHUNK 4096
inf(FILE * source,char * dest)174*cf5a6c84SAndroid Build Coastguard Worker int inf(FILE *source, char *dest) //modified signature to ease use
175*cf5a6c84SAndroid Build Coastguard Worker {
176*cf5a6c84SAndroid Build Coastguard Worker int ret;
177*cf5a6c84SAndroid Build Coastguard Worker char *position = dest;
178*cf5a6c84SAndroid Build Coastguard Worker unsigned have;
179*cf5a6c84SAndroid Build Coastguard Worker z_stream strm;
180*cf5a6c84SAndroid Build Coastguard Worker unsigned char in[CHUNK];
181*cf5a6c84SAndroid Build Coastguard Worker unsigned char out[CHUNK];
182*cf5a6c84SAndroid Build Coastguard Worker strm.zalloc = Z_NULL;
183*cf5a6c84SAndroid Build Coastguard Worker strm.zfree = Z_NULL;
184*cf5a6c84SAndroid Build Coastguard Worker strm.opaque = Z_NULL;
185*cf5a6c84SAndroid Build Coastguard Worker strm.avail_in = 0;
186*cf5a6c84SAndroid Build Coastguard Worker strm.next_in = Z_NULL;
187*cf5a6c84SAndroid Build Coastguard Worker ret = inflateInit(&strm);
188*cf5a6c84SAndroid Build Coastguard Worker if (ret != Z_OK) return ret;
189*cf5a6c84SAndroid Build Coastguard Worker
190*cf5a6c84SAndroid Build Coastguard Worker // decompress until deflate stream ends or end of file
191*cf5a6c84SAndroid Build Coastguard Worker do {
192*cf5a6c84SAndroid Build Coastguard Worker
193*cf5a6c84SAndroid Build Coastguard Worker strm.avail_in = fread(in, 1, CHUNK, source);
194*cf5a6c84SAndroid Build Coastguard Worker if (ferror(source)) {
195*cf5a6c84SAndroid Build Coastguard Worker (void)inflateEnd(&strm);
196*cf5a6c84SAndroid Build Coastguard Worker
197*cf5a6c84SAndroid Build Coastguard Worker return Z_ERRNO;
198*cf5a6c84SAndroid Build Coastguard Worker }
199*cf5a6c84SAndroid Build Coastguard Worker if (strm.avail_in == 0)
200*cf5a6c84SAndroid Build Coastguard Worker break;
201*cf5a6c84SAndroid Build Coastguard Worker strm.next_in = in;
202*cf5a6c84SAndroid Build Coastguard Worker
203*cf5a6c84SAndroid Build Coastguard Worker
204*cf5a6c84SAndroid Build Coastguard Worker // run inflate() on input until output buffer not full
205*cf5a6c84SAndroid Build Coastguard Worker do {
206*cf5a6c84SAndroid Build Coastguard Worker
207*cf5a6c84SAndroid Build Coastguard Worker strm.avail_out = CHUNK;
208*cf5a6c84SAndroid Build Coastguard Worker strm.next_out = out;
209*cf5a6c84SAndroid Build Coastguard Worker
210*cf5a6c84SAndroid Build Coastguard Worker ret = inflate(&strm, Z_NO_FLUSH);
211*cf5a6c84SAndroid Build Coastguard Worker //assert(ret != Z_STREAM_ERROR); // state not clobbered
212*cf5a6c84SAndroid Build Coastguard Worker switch (ret) {
213*cf5a6c84SAndroid Build Coastguard Worker case Z_NEED_DICT:
214*cf5a6c84SAndroid Build Coastguard Worker ret = Z_DATA_ERROR; // and fall through
215*cf5a6c84SAndroid Build Coastguard Worker case Z_DATA_ERROR:
216*cf5a6c84SAndroid Build Coastguard Worker case Z_MEM_ERROR:
217*cf5a6c84SAndroid Build Coastguard Worker (void)inflateEnd(&strm);
218*cf5a6c84SAndroid Build Coastguard Worker
219*cf5a6c84SAndroid Build Coastguard Worker return ret;
220*cf5a6c84SAndroid Build Coastguard Worker }
221*cf5a6c84SAndroid Build Coastguard Worker
222*cf5a6c84SAndroid Build Coastguard Worker have = CHUNK - strm.avail_out;
223*cf5a6c84SAndroid Build Coastguard Worker memcpy(position, out, have); //added to original
224*cf5a6c84SAndroid Build Coastguard Worker position += have; //added to original
225*cf5a6c84SAndroid Build Coastguard Worker //if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
226*cf5a6c84SAndroid Build Coastguard Worker // (void)inflateEnd(&strm);
227*cf5a6c84SAndroid Build Coastguard Worker // return Z_ERRNO;
228*cf5a6c84SAndroid Build Coastguard Worker //}
229*cf5a6c84SAndroid Build Coastguard Worker } while (strm.avail_out == 0);
230*cf5a6c84SAndroid Build Coastguard Worker // done when inflate() says it's done
231*cf5a6c84SAndroid Build Coastguard Worker } while (ret != Z_STREAM_END);
232*cf5a6c84SAndroid Build Coastguard Worker // modified from zpipe.c to set FP to end of zlib object
233*cf5a6c84SAndroid Build Coastguard Worker fseek(source, ftell(source)-strm.avail_in, SEEK_SET);
234*cf5a6c84SAndroid Build Coastguard Worker // clean up and return
235*cf5a6c84SAndroid Build Coastguard Worker (void)inflateEnd(&strm);
236*cf5a6c84SAndroid Build Coastguard Worker
237*cf5a6c84SAndroid Build Coastguard Worker return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
238*cf5a6c84SAndroid Build Coastguard Worker }
239*cf5a6c84SAndroid Build Coastguard Worker
240*cf5a6c84SAndroid Build Coastguard Worker //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L72
241*cf5a6c84SAndroid Build Coastguard Worker //Set object to the index after adding prefix, calculating the hash and finding the position
set_object(struct IndexV2 * idx,int type,char * o,unsigned count,unsigned ofs)242*cf5a6c84SAndroid Build Coastguard Worker long set_object(struct IndexV2 *idx, int type, char *o, unsigned count,
243*cf5a6c84SAndroid Build Coastguard Worker unsigned ofs)
244*cf5a6c84SAndroid Build Coastguard Worker {
245*cf5a6c84SAndroid Build Coastguard Worker // TODO: Too many allocs in here 1) to concat the search string for hashing
246*cf5a6c84SAndroid Build Coastguard Worker // 2) to insert into the array (can be reduce to a single malloc in fetch as
247*cf5a6c84SAndroid Build Coastguard Worker // the pack header contains the number of objects in pack
248*cf5a6c84SAndroid Build Coastguard Worker char *c, *p = "", *h = xmalloc(20); //composition,prefix,hash
249*cf5a6c84SAndroid Build Coastguard Worker long pos = 0;
250*cf5a6c84SAndroid Build Coastguard Worker
251*cf5a6c84SAndroid Build Coastguard Worker printf("Alloc... ");
252*cf5a6c84SAndroid Build Coastguard Worker //append a object prefix based on its type (not included in packfile)
253*cf5a6c84SAndroid Build Coastguard Worker switch(type) {
254*cf5a6c84SAndroid Build Coastguard Worker case 1: p = xmprintf("commit %d", count); break; //count is used as o can contain \0 in the string
255*cf5a6c84SAndroid Build Coastguard Worker case 2: p = xmprintf("tree %d", count); break;
256*cf5a6c84SAndroid Build Coastguard Worker case 3: p = xmprintf("blob %d", count); break;
257*cf5a6c84SAndroid Build Coastguard Worker case 4: p = xmprintf("tag %d", count); break;
258*cf5a6c84SAndroid Build Coastguard Worker case 6: printf("REF_DELTA"); break; //not expected in fetch packs as fetch packs are self-containing
259*cf5a6c84SAndroid Build Coastguard Worker case 7: printf("OBJ_DELTA\n"); break;
260*cf5a6c84SAndroid Build Coastguard Worker }
261*cf5a6c84SAndroid Build Coastguard Worker c = xmalloc(strlen(p)+count+2);
262*cf5a6c84SAndroid Build Coastguard Worker memcpy(c, p, strlen(p)+1);
263*cf5a6c84SAndroid Build Coastguard Worker memcpy(c+strlen(p)+1, o, count+1);
264*cf5a6c84SAndroid Build Coastguard Worker h = SHA1(c, strlen(p)+count+1, h); //ToDo: borrowed from OpenSSL to not to pipe or refactor SHA1SUM in toybox
265*cf5a6c84SAndroid Build Coastguard Worker printf("..Binary search\n");
266*cf5a6c84SAndroid Build Coastguard Worker for (int j = 0; j<20; j++) printf("%02x", h[j]); //find insert position
267*cf5a6c84SAndroid Build Coastguard Worker pos = bsearchpos(h, idx->sha1[0], idx->fot[255], 20);
268*cf5a6c84SAndroid Build Coastguard Worker printf("\n..Insert pos %ld\n", pos);
269*cf5a6c84SAndroid Build Coastguard Worker printf("..Preloop\n");
270*cf5a6c84SAndroid Build Coastguard Worker
271*cf5a6c84SAndroid Build Coastguard Worker //adjust of fanout table https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L204
272*cf5a6c84SAndroid Build Coastguard Worker for (int i = h[0]; i<=255; i++) idx->fot[i] += 1;
273*cf5a6c84SAndroid Build Coastguard Worker printf("Post loop\n");
274*cf5a6c84SAndroid Build Coastguard Worker printf("Resize sha1 array..idx->fot[255]%d\n", idx->fot[255]); //Memory management for insert
275*cf5a6c84SAndroid Build Coastguard Worker //TODO:Could be also a single malloc at gitfetch based on the nbr of objects in pack
276*cf5a6c84SAndroid Build Coastguard Worker
277*cf5a6c84SAndroid Build Coastguard Worker //Did not fix the TODO yet, because set_object could be reused for other commands adding single objects to the index
278*cf5a6c84SAndroid Build Coastguard Worker idx->sha1 = realloc(idx->sha1, (idx->fot[255]+1)*20*sizeof(char));
279*cf5a6c84SAndroid Build Coastguard Worker printf("Mem copy sha1 array..sizeof(idx->sha1)%zu\n", sizeof(idx->sha1));
280*cf5a6c84SAndroid Build Coastguard Worker memmove(&idx->sha1[pos+1], &idx->sha1[pos], (idx->fot[255]-pos)*20*sizeof(char));
281*cf5a6c84SAndroid Build Coastguard Worker printf("Resize offset\n");
282*cf5a6c84SAndroid Build Coastguard Worker idx->offset = realloc(idx->offset, (idx->fot[255]+1)*sizeof(unsigned));
283*cf5a6c84SAndroid Build Coastguard Worker printf("Mem copy offset\n");
284*cf5a6c84SAndroid Build Coastguard Worker memmove(&idx->offset[pos+1], &idx->offset[pos], sizeof(unsigned)*(idx->fot[255]-pos));
285*cf5a6c84SAndroid Build Coastguard Worker printf("Set offset value\n");
286*cf5a6c84SAndroid Build Coastguard Worker memcpy(&idx->sha1[pos], h, 20); //insert SHA1
287*cf5a6c84SAndroid Build Coastguard Worker idx->offset[pos] = ofs; //insert offset of SHA1
288*cf5a6c84SAndroid Build Coastguard Worker //ToDo: id->crc[idx->fot[h[0]]]=;
289*cf5a6c84SAndroid Build Coastguard Worker printf("Write object\n");
290*cf5a6c84SAndroid Build Coastguard Worker free(h);
291*cf5a6c84SAndroid Build Coastguard Worker free(c);
292*cf5a6c84SAndroid Build Coastguard Worker
293*cf5a6c84SAndroid Build Coastguard Worker return ofs;
294*cf5a6c84SAndroid Build Coastguard Worker }
295*cf5a6c84SAndroid Build Coastguard Worker
296*cf5a6c84SAndroid Build Coastguard Worker //init a git repository in a given directory name
gitinit(char * name)297*cf5a6c84SAndroid Build Coastguard Worker static void gitinit(char *name)
298*cf5a6c84SAndroid Build Coastguard Worker {
299*cf5a6c84SAndroid Build Coastguard Worker //For git clone actually only refs and object/pack are needed
300*cf5a6c84SAndroid Build Coastguard Worker if (mkdir(name, 0755)!=0){
301*cf5a6c84SAndroid Build Coastguard Worker //I create the others for a git compliant folder structure
302*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git"), 0755);
303*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/objects"), 0755);
304*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/objects/pack"), 0755);
305*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/branches"), 0755);
306*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/hooks"), 0755); //hook files skipped as implementations does not support hooks
307*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/info"), 0755);
308*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/objects/info"), 0755);
309*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/refs"), 0755);
310*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/heads"), 0755);
311*cf5a6c84SAndroid Build Coastguard Worker mkdir(xmprintf("%s%s", name, "/.git/tags"), 0755);
312*cf5a6c84SAndroid Build Coastguard Worker xcreate(xmprintf("%s%s", name, "/.git/config"), O_CREAT, 0644);
313*cf5a6c84SAndroid Build Coastguard Worker xcreate(xmprintf("%s%s", name, "/.git/description"), O_CREAT, 0644);
314*cf5a6c84SAndroid Build Coastguard Worker xcreate(xmprintf("%s%s", name, "/.git/HEAD"), O_CREAT, 0644);
315*cf5a6c84SAndroid Build Coastguard Worker xcreate(xmprintf("%s%s", name, "/.git/info/exclude"), O_CREAT, 0644);
316*cf5a6c84SAndroid Build Coastguard Worker }
317*cf5a6c84SAndroid Build Coastguard Worker }
318*cf5a6c84SAndroid Build Coastguard Worker
319*cf5a6c84SAndroid Build Coastguard Worker //set basic configuration and add remote URL
gitremote(char * url)320*cf5a6c84SAndroid Build Coastguard Worker static void gitremote(char *url)
321*cf5a6c84SAndroid Build Coastguard Worker {
322*cf5a6c84SAndroid Build Coastguard Worker if (access(".git/config", F_OK)!=0) {
323*cf5a6c84SAndroid Build Coastguard Worker FILE *fp = fopen(".git/config", "wb");
324*cf5a6c84SAndroid Build Coastguard Worker
325*cf5a6c84SAndroid Build Coastguard Worker fwrite("[core]\n", 1, 7, fp);
326*cf5a6c84SAndroid Build Coastguard Worker fwrite("\trepositoryformatversion = 0\n", 1, 29, fp);
327*cf5a6c84SAndroid Build Coastguard Worker fwrite("\tfilemode = false\n", 1, 18, fp);
328*cf5a6c84SAndroid Build Coastguard Worker fwrite("\tbare = false\n", 1, 14, fp);
329*cf5a6c84SAndroid Build Coastguard Worker fwrite("\tlogallrefupdates = true\n", 1, 25, fp);
330*cf5a6c84SAndroid Build Coastguard Worker fwrite("\tsymlinks = false\n", 1, 18, fp);
331*cf5a6c84SAndroid Build Coastguard Worker fwrite("\tignorecase = true\n", 1, 19, fp);
332*cf5a6c84SAndroid Build Coastguard Worker fwrite("[remote \"origin\"]\n", 1, 18, fp);
333*cf5a6c84SAndroid Build Coastguard Worker fwrite(xmprintf("\turl = %s/refs\n", TT.url), 1, strlen(TT.url)+13, fp);
334*cf5a6c84SAndroid Build Coastguard Worker fwrite("\tfetch = +ref/heads/*:refs/remotes/origin/*\n", 1, 44, fp);
335*cf5a6c84SAndroid Build Coastguard Worker fclose(fp);
336*cf5a6c84SAndroid Build Coastguard Worker }
337*cf5a6c84SAndroid Build Coastguard Worker }
338*cf5a6c84SAndroid Build Coastguard Worker
339*cf5a6c84SAndroid Build Coastguard Worker // this is most likely still buggy and create a late observable heap overflow larger deltafied repos
340*cf5a6c84SAndroid Build Coastguard Worker // https://stackoverflow.com/a/14303988
341*cf5a6c84SAndroid Build Coastguard Worker // resolve deltafied objects in the pack file, see URL in comments for further explainations
resolve_delta(char * s,char * d,long dsize,unsigned * count)342*cf5a6c84SAndroid Build Coastguard Worker char *resolve_delta(char *s, char *d, long dsize, unsigned *count)
343*cf5a6c84SAndroid Build Coastguard Worker {
344*cf5a6c84SAndroid Build Coastguard Worker long pos = 0, bitshift = 0;
345*cf5a6c84SAndroid Build Coastguard Worker //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L113
346*cf5a6c84SAndroid Build Coastguard Worker // Skipping source size; did not find out why it is on the delta header as the source object header contains it too; maybe misunderstood and this makes things buggy, but I dont need it here
347*cf5a6c84SAndroid Build Coastguard Worker while ((d[pos] & 0x80)) pos++;
348*cf5a6c84SAndroid Build Coastguard Worker pos++; //fixes https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L114
349*cf5a6c84SAndroid Build Coastguard Worker *count = 0;
350*cf5a6c84SAndroid Build Coastguard Worker bitshift = 0;
351*cf5a6c84SAndroid Build Coastguard Worker while ((d[pos] & 0x80)) { //reading target_size from header
352*cf5a6c84SAndroid Build Coastguard Worker *count |= (unsigned long long)(d[pos++]& 0x7F) << bitshift;
353*cf5a6c84SAndroid Build Coastguard Worker bitshift += 7; // (*offset)++;
354*cf5a6c84SAndroid Build Coastguard Worker }
355*cf5a6c84SAndroid Build Coastguard Worker
356*cf5a6c84SAndroid Build Coastguard Worker *count |= (unsigned long long)(d[pos++]& 0x7F) << bitshift;
357*cf5a6c84SAndroid Build Coastguard Worker printf("Target Count %d:\n", *count);
358*cf5a6c84SAndroid Build Coastguard Worker char *t = xmalloc(*count+1);
359*cf5a6c84SAndroid Build Coastguard Worker *count = 0;
360*cf5a6c84SAndroid Build Coastguard Worker while (pos<dsize) {
361*cf5a6c84SAndroid Build Coastguard Worker int i = 0, j = 1;
362*cf5a6c84SAndroid Build Coastguard Worker unsigned offset = 0, size = 0;
363*cf5a6c84SAndroid Build Coastguard Worker
364*cf5a6c84SAndroid Build Coastguard Worker if ((d[pos]&0x80)) {//https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L128
365*cf5a6c84SAndroid Build Coastguard Worker //https://stackoverflow.com/a/14303988
366*cf5a6c84SAndroid Build Coastguard Worker printf("Case 1\n");
367*cf5a6c84SAndroid Build Coastguard Worker while (i<4) {
368*cf5a6c84SAndroid Build Coastguard Worker if (d[pos]&(1<<i)) {
369*cf5a6c84SAndroid Build Coastguard Worker offset |= d[pos+j]<<(i*8);
370*cf5a6c84SAndroid Build Coastguard Worker j++;
371*cf5a6c84SAndroid Build Coastguard Worker }
372*cf5a6c84SAndroid Build Coastguard Worker i++;
373*cf5a6c84SAndroid Build Coastguard Worker }
374*cf5a6c84SAndroid Build Coastguard Worker while (i<7) {
375*cf5a6c84SAndroid Build Coastguard Worker if (d[pos]&(1<<i)) {
376*cf5a6c84SAndroid Build Coastguard Worker size |= d[pos+j]<<(i*8);
377*cf5a6c84SAndroid Build Coastguard Worker j++;
378*cf5a6c84SAndroid Build Coastguard Worker }
379*cf5a6c84SAndroid Build Coastguard Worker i++;
380*cf5a6c84SAndroid Build Coastguard Worker }
381*cf5a6c84SAndroid Build Coastguard Worker
382*cf5a6c84SAndroid Build Coastguard Worker // packfomat: size zero is automatically converted to 0x10000.
383*cf5a6c84SAndroid Build Coastguard Worker // https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L156
384*cf5a6c84SAndroid Build Coastguard Worker if (size==0) size = 0x10000;
385*cf5a6c84SAndroid Build Coastguard Worker memcpy(t+*count, s+offset, size);
386*cf5a6c84SAndroid Build Coastguard Worker //t[size] = '\0';
387*cf5a6c84SAndroid Build Coastguard Worker pos += j;
388*cf5a6c84SAndroid Build Coastguard Worker printf("Pos\n");
389*cf5a6c84SAndroid Build Coastguard Worker } else {
390*cf5a6c84SAndroid Build Coastguard Worker //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L158
391*cf5a6c84SAndroid Build Coastguard Worker printf("Case 0\n");
392*cf5a6c84SAndroid Build Coastguard Worker size = d[pos++]; //incrememt
393*cf5a6c84SAndroid Build Coastguard Worker memcpy(t+*count, d+pos, size);
394*cf5a6c84SAndroid Build Coastguard Worker pos += size;
395*cf5a6c84SAndroid Build Coastguard Worker }
396*cf5a6c84SAndroid Build Coastguard Worker *count += size;
397*cf5a6c84SAndroid Build Coastguard Worker
398*cf5a6c84SAndroid Build Coastguard Worker printf("Target: \n");
399*cf5a6c84SAndroid Build Coastguard Worker }
400*cf5a6c84SAndroid Build Coastguard Worker free(s);
401*cf5a6c84SAndroid Build Coastguard Worker free(d);
402*cf5a6c84SAndroid Build Coastguard Worker
403*cf5a6c84SAndroid Build Coastguard Worker return t;
404*cf5a6c84SAndroid Build Coastguard Worker }
405*cf5a6c84SAndroid Build Coastguard Worker
406*cf5a6c84SAndroid Build Coastguard Worker //unpack object (,resolve deltafied objects recursively) and return the unpacked object
unpack_object(FILE * fpp,struct IndexV2 * i,long offset,unsigned * count,int * type)407*cf5a6c84SAndroid Build Coastguard Worker char *unpack_object(FILE *fpp, struct IndexV2 *i, long offset, unsigned *count,
408*cf5a6c84SAndroid Build Coastguard Worker int *type)
409*cf5a6c84SAndroid Build Coastguard Worker {
410*cf5a6c84SAndroid Build Coastguard Worker unsigned dcount = unpack(fpp, type, &offset);
411*cf5a6c84SAndroid Build Coastguard Worker char *object = xmalloc(dcount);
412*cf5a6c84SAndroid Build Coastguard Worker
413*cf5a6c84SAndroid Build Coastguard Worker object[*count] = '\0';
414*cf5a6c84SAndroid Build Coastguard Worker printf("Count: %d \n", *count);
415*cf5a6c84SAndroid Build Coastguard Worker // see OBJ_REF_DELTA here https://yqintl.alicdn.com/eef7fe4f22cc97912cee011c99d3fe5821ae9e88.png
416*cf5a6c84SAndroid Build Coastguard Worker if (*type==7) {
417*cf5a6c84SAndroid Build Coastguard Worker char *h = xmalloc(20);
418*cf5a6c84SAndroid Build Coastguard Worker
419*cf5a6c84SAndroid Build Coastguard Worker fread(h, 20, 1, fpp); //fseek(fpp, 20, SEEK_CUR);
420*cf5a6c84SAndroid Build Coastguard Worker printf("Read base object\n");
421*cf5a6c84SAndroid Build Coastguard Worker for (int j = 0; j<20; j++) printf("%02x", h[j]);
422*cf5a6c84SAndroid Build Coastguard Worker printf("\n");
423*cf5a6c84SAndroid Build Coastguard Worker inf(fpp, object); //TO CHECK IF INF OR PLAIN TEXT:
424*cf5a6c84SAndroid Build Coastguard Worker long toffset = ftell(fpp); //save original file offset
425*cf5a6c84SAndroid Build Coastguard Worker char *source = unpack_object(fpp, i, get_index(i, h), count, type);
426*cf5a6c84SAndroid Build Coastguard Worker printf("Inflate delta data\n");
427*cf5a6c84SAndroid Build Coastguard Worker fseek(fpp, toffset, SEEK_SET); //return to original file offset
428*cf5a6c84SAndroid Build Coastguard Worker printf("Resolve delta data\n");
429*cf5a6c84SAndroid Build Coastguard Worker free(h);//recursion due to https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L58
430*cf5a6c84SAndroid Build Coastguard Worker return resolve_delta(source, object, dcount, count);
431*cf5a6c84SAndroid Build Coastguard Worker } else {
432*cf5a6c84SAndroid Build Coastguard Worker printf("Type Else:\n");
433*cf5a6c84SAndroid Build Coastguard Worker inf(fpp, object);
434*cf5a6c84SAndroid Build Coastguard Worker *count = dcount;
435*cf5a6c84SAndroid Build Coastguard Worker printf("Type Else end:\n");
436*cf5a6c84SAndroid Build Coastguard Worker //printf("Unpacked Object: %s\n", object);
437*cf5a6c84SAndroid Build Coastguard Worker
438*cf5a6c84SAndroid Build Coastguard Worker return object;
439*cf5a6c84SAndroid Build Coastguard Worker }
440*cf5a6c84SAndroid Build Coastguard Worker }
441*cf5a6c84SAndroid Build Coastguard Worker
442*cf5a6c84SAndroid Build Coastguard Worker //make 20byte SHA1 hash from 40 byte SHA1 string
txtoh(char * p)443*cf5a6c84SAndroid Build Coastguard Worker char *txtoh(char *p)
444*cf5a6c84SAndroid Build Coastguard Worker {
445*cf5a6c84SAndroid Build Coastguard Worker //TODO: Dont like the malloc here, but did not find a solution to sscanf into p again
446*cf5a6c84SAndroid Build Coastguard Worker char *h = xmalloc(41);
447*cf5a6c84SAndroid Build Coastguard Worker
448*cf5a6c84SAndroid Build Coastguard Worker for (int c = 0; c<20; c++) {
449*cf5a6c84SAndroid Build Coastguard Worker sscanf(&p[2*c], "%2hhx", &(h[c]));
450*cf5a6c84SAndroid Build Coastguard Worker }
451*cf5a6c84SAndroid Build Coastguard Worker h[20] = 0;
452*cf5a6c84SAndroid Build Coastguard Worker printf("return");
453*cf5a6c84SAndroid Build Coastguard Worker
454*cf5a6c84SAndroid Build Coastguard Worker return h;
455*cf5a6c84SAndroid Build Coastguard Worker }
456*cf5a6c84SAndroid Build Coastguard Worker
457*cf5a6c84SAndroid Build Coastguard Worker //traveres the commit tree for checkout
write_children(char * hash,char * path,FILE * fpp)458*cf5a6c84SAndroid Build Coastguard Worker void write_children(char *hash, char *path, FILE *fpp)
459*cf5a6c84SAndroid Build Coastguard Worker {
460*cf5a6c84SAndroid Build Coastguard Worker FILE *fc;
461*cf5a6c84SAndroid Build Coastguard Worker char *object;
462*cf5a6c84SAndroid Build Coastguard Worker int type;
463*cf5a6c84SAndroid Build Coastguard Worker long offset;
464*cf5a6c84SAndroid Build Coastguard Worker unsigned count=0;
465*cf5a6c84SAndroid Build Coastguard Worker
466*cf5a6c84SAndroid Build Coastguard Worker printf("seek index\n");
467*cf5a6c84SAndroid Build Coastguard Worker
468*cf5a6c84SAndroid Build Coastguard Worker offset = get_index(TT.i, hash);
469*cf5a6c84SAndroid Build Coastguard Worker printf("Found index: %ld\n", offset);
470*cf5a6c84SAndroid Build Coastguard Worker printf("read object\n");
471*cf5a6c84SAndroid Build Coastguard Worker object = unpack_object(fpp, TT.i, offset, &count, &type);
472*cf5a6c84SAndroid Build Coastguard Worker printf("%s\n", object);
473*cf5a6c84SAndroid Build Coastguard Worker printf("Type %d\n", type);
474*cf5a6c84SAndroid Build Coastguard Worker if (type==1) { //at commit object
475*cf5a6c84SAndroid Build Coastguard Worker memcpy(hash, object+5, 40);
476*cf5a6c84SAndroid Build Coastguard Worker write_children(txtoh(hash), path, fpp);
477*cf5a6c84SAndroid Build Coastguard Worker } else if (type==2) { //at tree object https://stackoverflow.com/a/21599232
478*cf5a6c84SAndroid Build Coastguard Worker char *hs, *name;
479*cf5a6c84SAndroid Build Coastguard Worker int pos = 0;
480*cf5a6c84SAndroid Build Coastguard Worker
481*cf5a6c84SAndroid Build Coastguard Worker printf("process folder %s\n", path);
482*cf5a6c84SAndroid Build Coastguard Worker while (pos<count){
483*cf5a6c84SAndroid Build Coastguard Worker //find position where the next hash starts
484*cf5a6c84SAndroid Build Coastguard Worker hs = object+pos;
485*cf5a6c84SAndroid Build Coastguard Worker printf("Object+pos: %s\n", hs);
486*cf5a6c84SAndroid Build Coastguard Worker // memcpy(mode, hs+2, 3)//TODO:String to umask
487*cf5a6c84SAndroid Build Coastguard Worker if (*hs=='1') { //tree object reference is a file
488*cf5a6c84SAndroid Build Coastguard Worker // concat file name
489*cf5a6c84SAndroid Build Coastguard Worker name = *path ? xmprintf("%s/%s", path, hs+7) : hs+7;
490*cf5a6c84SAndroid Build Coastguard Worker printf("prepare file %s\n", name);
491*cf5a6c84SAndroid Build Coastguard Worker } else { //tree object reference is a folder
492*cf5a6c84SAndroid Build Coastguard Worker // concat folder name
493*cf5a6c84SAndroid Build Coastguard Worker name = *path ? xmprintf("%s/%s", path, hs+6) : hs+6;
494*cf5a6c84SAndroid Build Coastguard Worker printf("create folder %s\n", name);
495*cf5a6c84SAndroid Build Coastguard Worker mkdir(name, 0755); //TODO: umask
496*cf5a6c84SAndroid Build Coastguard Worker }
497*cf5a6c84SAndroid Build Coastguard Worker hs += strlen(hs)+1;
498*cf5a6c84SAndroid Build Coastguard Worker memcpy(hash, hs, 20);
499*cf5a6c84SAndroid Build Coastguard Worker write_children(hash, name, fpp);
500*cf5a6c84SAndroid Build Coastguard Worker pos = hs-object+20;
501*cf5a6c84SAndroid Build Coastguard Worker printf("Position/count for %s: %d/%u\n", path, pos, count);
502*cf5a6c84SAndroid Build Coastguard Worker }
503*cf5a6c84SAndroid Build Coastguard Worker printf("**EXIT WHILE**\n");
504*cf5a6c84SAndroid Build Coastguard Worker } else { //at blob/file object
505*cf5a6c84SAndroid Build Coastguard Worker printf("process file %s\n", path);
506*cf5a6c84SAndroid Build Coastguard Worker fc = fopen(path, "w");
507*cf5a6c84SAndroid Build Coastguard Worker printf("process opened \n");
508*cf5a6c84SAndroid Build Coastguard Worker fputs(object, fc); //TODO:Not sure if length might be an issue here
509*cf5a6c84SAndroid Build Coastguard Worker printf("process file written\n");
510*cf5a6c84SAndroid Build Coastguard Worker fclose(fc);
511*cf5a6c84SAndroid Build Coastguard Worker }
512*cf5a6c84SAndroid Build Coastguard Worker free(object);
513*cf5a6c84SAndroid Build Coastguard Worker printf("Child: %s done\n", path);
514*cf5a6c84SAndroid Build Coastguard Worker }
515*cf5a6c84SAndroid Build Coastguard Worker
516*cf5a6c84SAndroid Build Coastguard Worker //fetches the meta data from the remote repository,requests a pack file for the remote master head,
517*cf5a6c84SAndroid Build Coastguard Worker //unpacks all objects and set objects to the index
gitfetch(void)518*cf5a6c84SAndroid Build Coastguard Worker static void gitfetch(void)
519*cf5a6c84SAndroid Build Coastguard Worker {
520*cf5a6c84SAndroid Build Coastguard Worker printf("refs\n");
521*cf5a6c84SAndroid Build Coastguard Worker
522*cf5a6c84SAndroid Build Coastguard Worker // TODO:I use herein after two temp files for fetch which git does not offer
523*cf5a6c84SAndroid Build Coastguard Worker // to 1) avoid a rewrite and 2) messing up the repo files while testing
524*cf5a6c84SAndroid Build Coastguard Worker
525*cf5a6c84SAndroid Build Coastguard Worker // TODO: Refactor wget into lib
526*cf5a6c84SAndroid Build Coastguard Worker xrun((char *[]){"wget", "-O", ".git/refs/temp.refs",
527*cf5a6c84SAndroid Build Coastguard Worker "https://github.com/landley/toybox/info/refs?service=git-upload-pack",
528*cf5a6c84SAndroid Build Coastguard Worker 0});
529*cf5a6c84SAndroid Build Coastguard Worker //char h[] = "8cf1722f0fde510ea81d13b31bde1e48917a0306";
530*cf5a6c84SAndroid Build Coastguard Worker //TODO: Replace static testing hash and uncomment the following line if rare delta resolve /?heap overflow? bug was found
531*cf5a6c84SAndroid Build Coastguard Worker FILE *fpr = fopen(".git/refs/temp.refs", "r");
532*cf5a6c84SAndroid Build Coastguard Worker char *h;
533*cf5a6c84SAndroid Build Coastguard Worker size_t l = 0;
534*cf5a6c84SAndroid Build Coastguard Worker
535*cf5a6c84SAndroid Build Coastguard Worker getline(&h,&l,fpr);
536*cf5a6c84SAndroid Build Coastguard Worker getline(&h,&l,fpr);
537*cf5a6c84SAndroid Build Coastguard Worker getline(&h,&l,fpr);
538*cf5a6c84SAndroid Build Coastguard Worker getline(&h,&l,fpr);
539*cf5a6c84SAndroid Build Coastguard Worker fclose(fpr);
540*cf5a6c84SAndroid Build Coastguard Worker strcpy(h,&h[4]);
541*cf5a6c84SAndroid Build Coastguard Worker h[40] = 0;
542*cf5a6c84SAndroid Build Coastguard Worker printf("Master HEAD hash: %s\n",h);
543*cf5a6c84SAndroid Build Coastguard Worker //TODO: Persist hash to /refs/master/HEAD
544*cf5a6c84SAndroid Build Coastguard Worker printf("pack\n");
545*cf5a6c84SAndroid Build Coastguard Worker xrun((char *[]){"toybox", "wget", "-O", ".git/objects/pack/temp.pack", "-p", xmprintf("$'0032want %s\n00000009done\n'", h), "https://github.com/landley/toybox/git-upload-pack", 0});
546*cf5a6c84SAndroid Build Coastguard Worker //TODO: does not skip 0008NAK printf("init\n");
547*cf5a6c84SAndroid Build Coastguard Worker FILE *fpp;
548*cf5a6c84SAndroid Build Coastguard Worker printf("openpack\n");
549*cf5a6c84SAndroid Build Coastguard Worker fpp = fopen(".git/objects/pack/temp.pack", "r");
550*cf5a6c84SAndroid Build Coastguard Worker printf("read index\n");
551*cf5a6c84SAndroid Build Coastguard Worker read_index(TT.i); //init index with out reading
552*cf5a6c84SAndroid Build Coastguard Worker printf("init\n");
553*cf5a6c84SAndroid Build Coastguard Worker unsigned ocount = 0, count;
554*cf5a6c84SAndroid Build Coastguard Worker int type;
555*cf5a6c84SAndroid Build Coastguard Worker char *object;
556*cf5a6c84SAndroid Build Coastguard Worker
557*cf5a6c84SAndroid Build Coastguard Worker printf("skip header\n");
558*cf5a6c84SAndroid Build Coastguard Worker long offset = 12+8; //8byte from the wget post response are skipped too
559*cf5a6c84SAndroid Build Coastguard Worker fseek(fpp, 8+8, SEEK_SET); //header check skipped //header check skipped https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L37
560*cf5a6c84SAndroid Build Coastguard Worker printf("read count\n");
561*cf5a6c84SAndroid Build Coastguard Worker fread(&ocount, 4, 1, fpp);
562*cf5a6c84SAndroid Build Coastguard Worker ocount = ntohl(ocount); //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L46
563*cf5a6c84SAndroid Build Coastguard Worker printf("Count: %d ..Loop pack\n", ocount);
564*cf5a6c84SAndroid Build Coastguard Worker for (int j = 0; j<ocount; j++){
565*cf5a6c84SAndroid Build Coastguard Worker printf("Read object %d\n", j);
566*cf5a6c84SAndroid Build Coastguard Worker count = 0;
567*cf5a6c84SAndroid Build Coastguard Worker object = unpack_object(fpp, TT.i, offset, &count, &type);
568*cf5a6c84SAndroid Build Coastguard Worker printf("Count: %d Offset: %ld ..Set object\n", count, offset);
569*cf5a6c84SAndroid Build Coastguard Worker set_object(TT.i, type, object, count, offset);
570*cf5a6c84SAndroid Build Coastguard Worker
571*cf5a6c84SAndroid Build Coastguard Worker free(object);
572*cf5a6c84SAndroid Build Coastguard Worker
573*cf5a6c84SAndroid Build Coastguard Worker printf("Adjust offset\n");
574*cf5a6c84SAndroid Build Coastguard Worker offset = ftell(fpp); //adjust offset to new file position
575*cf5a6c84SAndroid Build Coastguard Worker printf("Adjusted offset to: %ld\n", offset);
576*cf5a6c84SAndroid Build Coastguard Worker }
577*cf5a6c84SAndroid Build Coastguard Worker
578*cf5a6c84SAndroid Build Coastguard Worker //TODO: Final pack checksum not calculated and checked
579*cf5a6c84SAndroid Build Coastguard Worker fclose(fpp);
580*cf5a6c84SAndroid Build Coastguard Worker }
581*cf5a6c84SAndroid Build Coastguard Worker
582*cf5a6c84SAndroid Build Coastguard Worker //Checkout HEAD to the working directory by recursing write_children
583*cf5a6c84SAndroid Build Coastguard Worker //TODO: Replase static hashes with hash read from refs/<branch>/head
gitcheckout(char * name)584*cf5a6c84SAndroid Build Coastguard Worker static void gitcheckout(char *name)
585*cf5a6c84SAndroid Build Coastguard Worker {
586*cf5a6c84SAndroid Build Coastguard Worker
587*cf5a6c84SAndroid Build Coastguard Worker FILE *fpp;
588*cf5a6c84SAndroid Build Coastguard Worker //FILE *fh;
589*cf5a6c84SAndroid Build Coastguard Worker
590*cf5a6c84SAndroid Build Coastguard Worker printf("Find branch for checkout\n");
591*cf5a6c84SAndroid Build Coastguard Worker //fh = fopen(xmprintf(".git/ref/heads/%s", name ? "master" : name), "r"); //TODO: Checkout master as in ref/heads
592*cf5a6c84SAndroid Build Coastguard Worker printf("Read head\n");
593*cf5a6c84SAndroid Build Coastguard Worker //hf[fread(&hf, 40, 1, fh)] = '\0';
594*cf5a6c84SAndroid Build Coastguard Worker //fclose(fh);
595*cf5a6c84SAndroid Build Coastguard Worker printf("Close heads and read pack\n");
596*cf5a6c84SAndroid Build Coastguard Worker fpp = fopen(".git/objects/pack/temp.pack", "r");
597*cf5a6c84SAndroid Build Coastguard Worker printf("set signature\n");
598*cf5a6c84SAndroid Build Coastguard Worker char *p = "52fb04274b3491fdfe91b2e5acc23dc3f3064a86"; //static hashes for testing toybox 0.0.1";
599*cf5a6c84SAndroid Build Coastguard Worker //char *p = "c555a0ca46e75097596274bf5e634127015aa144"; //static hashes for testing 0.0.2";
600*cf5a6c84SAndroid Build Coastguard Worker //char *p = "4307a7b07cec4ad8cbab47a29ba941f8cb041812"; //static hashes for testing 0.0.3";
601*cf5a6c84SAndroid Build Coastguard Worker //char *p = "3632d5d8fe05d14da983e37c7cd34db0769e6238"; //static hashes for testing 0.0.4";
602*cf5a6c84SAndroid Build Coastguard Worker //char *p = "8cf1722f0fde510ea81d13b31bde1e48917a0306"; //3604ba4f42c3d83e2b14f6d0f423a33a3a8706c3";
603*cf5a6c84SAndroid Build Coastguard Worker printf("enter tree root\n");
604*cf5a6c84SAndroid Build Coastguard Worker write_children(txtoh(p), "", fpp);
605*cf5a6c84SAndroid Build Coastguard Worker fclose(fpp);
606*cf5a6c84SAndroid Build Coastguard Worker }
607*cf5a6c84SAndroid Build Coastguard Worker
gitclone_main(void)608*cf5a6c84SAndroid Build Coastguard Worker void gitclone_main(void)
609*cf5a6c84SAndroid Build Coastguard Worker {
610*cf5a6c84SAndroid Build Coastguard Worker TT.url = xstrdup(toys.optargs[0]);
611*cf5a6c84SAndroid Build Coastguard Worker if (strend(TT.url, ".git")) TT.url[strlen(TT.url)-4] = '\0';
612*cf5a6c84SAndroid Build Coastguard Worker TT.name = strrchr(TT.url, '/')+1;
613*cf5a6c84SAndroid Build Coastguard Worker gitinit(TT.name);
614*cf5a6c84SAndroid Build Coastguard Worker chdir(TT.name);
615*cf5a6c84SAndroid Build Coastguard Worker TT.i = malloc(sizeof(struct IndexV2));
616*cf5a6c84SAndroid Build Coastguard Worker gitremote(TT.url);
617*cf5a6c84SAndroid Build Coastguard Worker gitfetch();
618*cf5a6c84SAndroid Build Coastguard Worker gitcheckout("master");
619*cf5a6c84SAndroid Build Coastguard Worker chdir("..");
620*cf5a6c84SAndroid Build Coastguard Worker }
621*cf5a6c84SAndroid Build Coastguard Worker
622*cf5a6c84SAndroid Build Coastguard Worker #define FOR_gitinit
623*cf5a6c84SAndroid Build Coastguard Worker #include "generated/flags.h"
624*cf5a6c84SAndroid Build Coastguard Worker
gitinit_main(void)625*cf5a6c84SAndroid Build Coastguard Worker void gitinit_main(void)
626*cf5a6c84SAndroid Build Coastguard Worker {
627*cf5a6c84SAndroid Build Coastguard Worker gitinit(xstrdup(toys.optargs[0]));
628*cf5a6c84SAndroid Build Coastguard Worker }
629*cf5a6c84SAndroid Build Coastguard Worker
630*cf5a6c84SAndroid Build Coastguard Worker #define FOR_gitremote
631*cf5a6c84SAndroid Build Coastguard Worker
gitremote_main(void)632*cf5a6c84SAndroid Build Coastguard Worker void gitremote_main(void)
633*cf5a6c84SAndroid Build Coastguard Worker {
634*cf5a6c84SAndroid Build Coastguard Worker TT.url = xstrdup(toys.optargs[0]);
635*cf5a6c84SAndroid Build Coastguard Worker if (strend(TT.url, ".git")) TT.url[strlen(TT.url)-4] = '\0';
636*cf5a6c84SAndroid Build Coastguard Worker gitremote(TT.url);
637*cf5a6c84SAndroid Build Coastguard Worker }
638*cf5a6c84SAndroid Build Coastguard Worker
639*cf5a6c84SAndroid Build Coastguard Worker #define FOR_gitinit
640*cf5a6c84SAndroid Build Coastguard Worker
gitfetch_main(void)641*cf5a6c84SAndroid Build Coastguard Worker void gitfetch_main(void)
642*cf5a6c84SAndroid Build Coastguard Worker {
643*cf5a6c84SAndroid Build Coastguard Worker gitfetch();
644*cf5a6c84SAndroid Build Coastguard Worker }
645*cf5a6c84SAndroid Build Coastguard Worker
646*cf5a6c84SAndroid Build Coastguard Worker #define FOR_gitcheckout
647*cf5a6c84SAndroid Build Coastguard Worker
gitcheckout_main(void)648*cf5a6c84SAndroid Build Coastguard Worker void gitcheckout_main(void)
649*cf5a6c84SAndroid Build Coastguard Worker {
650*cf5a6c84SAndroid Build Coastguard Worker gitcheckout(xstrdup(toys.optargs[0]));
651*cf5a6c84SAndroid Build Coastguard Worker }
652*cf5a6c84SAndroid Build Coastguard Worker
653*cf5a6c84SAndroid Build Coastguard Worker // Command to wget refs and pack file using toybox wget to place them manually into the repository
654*cf5a6c84SAndroid Build Coastguard Worker // ./toybox wget -O - -d https://github.com/landley/toybox/info/refs?service=git-upload-pack | less
655*cf5a6c84SAndroid Build Coastguard Worker
656*cf5a6c84SAndroid Build Coastguard Worker // ./toybox wget -O pack.dat -d -p $'0032want 8cf1722f0fde510ea81d13b31bde1e48917a0306\n00000009done\n' https://github.com/landley/toybox/git-upload-pack
657