416ba5c7c6bacfbb62236326ffe02769cdee0199
1#include "builtin.h"
2#include "cache.h"
3#include "object.h"
4#include "blob.h"
5#include "delta.h"
6#include "pack.h"
7#include "csum-file.h"
8
9static int max_depth = 10;
10static unsigned long object_count;
11static int packfd;
12static int current_depth;
13static void *lastdat;
14static unsigned long lastdatlen;
15static unsigned char lastsha1[20];
16
17static ssize_t yread(int fd, void *buffer, size_t length)
18{
19 ssize_t ret = 0;
20 while (ret < length) {
21 ssize_t size = xread(fd, (char *) buffer + ret, length - ret);
22 if (size < 0) {
23 return size;
24 }
25 if (size == 0) {
26 return ret;
27 }
28 ret += size;
29 }
30 return ret;
31}
32
33static ssize_t ywrite(int fd, void *buffer, size_t length)
34{
35 ssize_t ret = 0;
36 while (ret < length) {
37 ssize_t size = xwrite(fd, (char *) buffer + ret, length - ret);
38 if (size < 0) {
39 return size;
40 }
41 if (size == 0) {
42 return ret;
43 }
44 ret += size;
45 }
46 return ret;
47}
48
49static unsigned long encode_header(enum object_type type, unsigned long size, unsigned char *hdr)
50{
51 int n = 1;
52 unsigned char c;
53
54 if (type < OBJ_COMMIT || type > OBJ_DELTA)
55 die("bad type %d", type);
56
57 c = (type << 4) | (size & 15);
58 size >>= 4;
59 while (size) {
60 *hdr++ = c | 0x80;
61 c = size & 0x7f;
62 size >>= 7;
63 n++;
64 }
65 *hdr = c;
66 return n;
67}
68
69static void write_blob (void *dat, unsigned long datlen)
70{
71 z_stream s;
72 void *out, *delta;
73 unsigned char hdr[64];
74 unsigned long hdrlen, deltalen;
75
76 if (lastdat && current_depth < max_depth) {
77 delta = diff_delta(lastdat, lastdatlen,
78 dat, datlen,
79 &deltalen, 0);
80 } else
81 delta = 0;
82
83 memset(&s, 0, sizeof(s));
84 deflateInit(&s, zlib_compression_level);
85
86 if (delta) {
87 current_depth++;
88 s.next_in = delta;
89 s.avail_in = deltalen;
90 hdrlen = encode_header(OBJ_DELTA, deltalen, hdr);
91 if (ywrite(packfd, hdr, hdrlen) != hdrlen)
92 die("Can't write object header: %s", strerror(errno));
93 if (ywrite(packfd, lastsha1, sizeof(lastsha1)) != sizeof(lastsha1))
94 die("Can't write object base: %s", strerror(errno));
95 } else {
96 current_depth = 0;
97 s.next_in = dat;
98 s.avail_in = datlen;
99 hdrlen = encode_header(OBJ_BLOB, datlen, hdr);
100 if (ywrite(packfd, hdr, hdrlen) != hdrlen)
101 die("Can't write object header: %s", strerror(errno));
102 }
103
104 s.avail_out = deflateBound(&s, s.avail_in);
105 s.next_out = out = xmalloc(s.avail_out);
106 while (deflate(&s, Z_FINISH) == Z_OK)
107 /* nothing */;
108 deflateEnd(&s);
109
110 if (ywrite(packfd, out, s.total_out) != s.total_out)
111 die("Failed writing compressed data %s", strerror(errno));
112
113 free(out);
114 if (delta)
115 free(delta);
116}
117
118static void init_pack_header ()
119{
120 const char* magic = "PACK";
121 unsigned long version = 2;
122 unsigned long zero = 0;
123
124 version = htonl(version);
125
126 if (ywrite(packfd, (char*)magic, 4) != 4)
127 die("Can't write pack magic: %s", strerror(errno));
128 if (ywrite(packfd, &version, 4) != 4)
129 die("Can't write pack version: %s", strerror(errno));
130 if (ywrite(packfd, &zero, 4) != 4)
131 die("Can't write 0 object count: %s", strerror(errno));
132}
133
134static void fixup_header_footer ()
135{
136 SHA_CTX c;
137 char hdr[8];
138 unsigned char sha1[20];
139 unsigned long cnt;
140 char *buf;
141 size_t n;
142
143 if (lseek(packfd, 0, SEEK_SET) != 0)
144 die("Failed seeking to start: %s", strerror(errno));
145
146 SHA1_Init(&c);
147 if (yread(packfd, hdr, 8) != 8)
148 die("Failed reading header: %s", strerror(errno));
149 SHA1_Update(&c, hdr, 8);
150
151fprintf(stderr, "%lu objects\n", object_count);
152 cnt = htonl(object_count);
153 SHA1_Update(&c, &cnt, 4);
154 if (ywrite(packfd, &cnt, 4) != 4)
155 die("Failed writing object count: %s", strerror(errno));
156
157 buf = xmalloc(128 * 1024);
158 for (;;) {
159 n = xread(packfd, buf, 128 * 1024);
160 if (n <= 0)
161 break;
162 SHA1_Update(&c, buf, n);
163 }
164 free(buf);
165
166 SHA1_Final(sha1, &c);
167 if (ywrite(packfd, sha1, sizeof(sha1)) != sizeof(sha1))
168 die("Failed writing pack checksum: %s", strerror(errno));
169}
170
171int main (int argc, const char **argv)
172{
173 packfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
174 if (packfd < 0)
175 die("Can't create pack file %s: %s", argv[1], strerror(errno));
176
177 init_pack_header();
178 for (;;) {
179 unsigned long datlen;
180 int hdrlen;
181 void *dat;
182 char hdr[128];
183 unsigned char sha1[20];
184 SHA_CTX c;
185
186 if (yread(0, &datlen, 4) != 4)
187 break;
188
189 dat = xmalloc(datlen);
190 if (yread(0, dat, datlen) != datlen)
191 break;
192
193 hdrlen = sprintf(hdr, "blob %lu", datlen) + 1;
194 SHA1_Init(&c);
195 SHA1_Update(&c, hdr, hdrlen);
196 SHA1_Update(&c, dat, datlen);
197 SHA1_Final(sha1, &c);
198
199 write_blob(dat, datlen);
200 object_count++;
201 printf("%s\n", sha1_to_hex(sha1));
202 fflush(stdout);
203
204 if (lastdat)
205 free(lastdat);
206 lastdat = dat;
207 lastdatlen = datlen;
208 memcpy(lastsha1, sha1, sizeof(sha1));
209 }
210 fixup_header_footer();
211 close(packfd);
212
213 return 0;
214}