]> git.ipfire.org Git - thirdparty/git.git/blame - builtin-unpack-objects.c
Merge branch 'jc/daemon'
[thirdparty/git.git] / builtin-unpack-objects.c
CommitLineData
64413630 1#include "builtin.h"
bad50dc8 2#include "cache.h"
74536958 3#include "object.h"
8ee378a0 4#include "delta.h"
a733cb60 5#include "pack.h"
8e440259
PE
6#include "blob.h"
7#include "commit.h"
8#include "tag.h"
9#include "tree.h"
bad50dc8 10
d36f7b80
LT
11#include <sys/time.h>
12
13static int dry_run, quiet;
b2309b70 14static const char unpack_usage[] = "git-unpack-objects [-n] [-q] < pack-file";
bad50dc8 15
67e5a5ec
LT
16/* We always read in 4kB chunks. */
17static unsigned char buffer[4096];
c9b0597d 18static unsigned long offset, len;
67e5a5ec 19static SHA_CTX ctx;
bad50dc8 20
67e5a5ec
LT
21/*
22 * Make sure at least "min" bytes are available in the buffer, and
23 * return the pointer to the buffer.
24 */
25static void * fill(int min)
26{
27 if (min <= len)
28 return buffer + offset;
67e5a5ec
LT
29 if (min > sizeof(buffer))
30 die("cannot fill %d bytes", min);
31 if (offset) {
32 SHA1_Update(&ctx, buffer, offset);
33 memcpy(buffer, buffer + offset, len);
34 offset = 0;
35 }
36 do {
1c15afb9 37 int ret = xread(0, buffer + len, sizeof(buffer) - len);
67e5a5ec
LT
38 if (ret <= 0) {
39 if (!ret)
40 die("early EOF");
67e5a5ec
LT
41 die("read error on input: %s", strerror(errno));
42 }
43 len += ret;
44 } while (len < min);
45 return buffer;
46}
74536958 47
67e5a5ec
LT
48static void use(int bytes)
49{
50 if (bytes > len)
51 die("used more bytes than were available");
52 len -= bytes;
53 offset += bytes;
54}
bad50dc8 55
67e5a5ec 56static void *get_data(unsigned long size)
bad50dc8 57{
67e5a5ec
LT
58 z_stream stream;
59 void *buf = xmalloc(size);
60
67e5a5ec
LT
61 memset(&stream, 0, sizeof(stream));
62
63 stream.next_out = buf;
64 stream.avail_out = size;
65 stream.next_in = fill(1);
66 stream.avail_in = len;
67 inflateInit(&stream);
68
69 for (;;) {
70 int ret = inflate(&stream, 0);
71 use(len - stream.avail_in);
72 if (stream.total_out == size && ret == Z_STREAM_END)
73 break;
74 if (ret != Z_OK)
75 die("inflate returned %d\n", ret);
76 stream.next_in = fill(1);
77 stream.avail_in = len;
78 }
ee639140 79 inflateEnd(&stream);
67e5a5ec 80 return buf;
bad50dc8
LT
81}
82
67e5a5ec
LT
83struct delta_info {
84 unsigned char base_sha1[20];
85 unsigned long size;
86 void *delta;
87 struct delta_info *next;
88};
89
90static struct delta_info *delta_list;
91
92static void add_delta_to_list(unsigned char *base_sha1, void *delta, unsigned long size)
bad50dc8 93{
67e5a5ec 94 struct delta_info *info = xmalloc(sizeof(*info));
bad50dc8 95
e702496e 96 hashcpy(info->base_sha1, base_sha1);
67e5a5ec
LT
97 info->size = size;
98 info->delta = delta;
99 info->next = delta_list;
100 delta_list = info;
bad50dc8
LT
101}
102
cca7081a 103static void added_object(unsigned char *sha1, const char *type, void *data, unsigned long size);
67e5a5ec 104
cca7081a
LT
105static void write_object(void *buf, unsigned long size, const char *type)
106{
107 unsigned char sha1[20];
108 if (write_sha1_file(buf, size, type, sha1) < 0)
109 die("failed to write object");
110 added_object(sha1, type, buf, size);
111}
112
113static int resolve_delta(const char *type,
64413630 114 void *base, unsigned long base_size,
67e5a5ec 115 void *delta, unsigned long delta_size)
bad50dc8 116{
67e5a5ec
LT
117 void *result;
118 unsigned long result_size;
bad50dc8 119
67e5a5ec
LT
120 result = patch_delta(base, base_size,
121 delta, delta_size,
122 &result_size);
123 if (!result)
124 die("failed to apply delta");
125 free(delta);
cca7081a 126 write_object(result, result_size, type);
67e5a5ec 127 free(result);
bad50dc8
LT
128 return 0;
129}
130
cca7081a 131static void added_object(unsigned char *sha1, const char *type, void *data, unsigned long size)
74536958 132{
67e5a5ec
LT
133 struct delta_info **p = &delta_list;
134 struct delta_info *info;
135
136 while ((info = *p) != NULL) {
a89fccd2 137 if (!hashcmp(info->base_sha1, sha1)) {
67e5a5ec
LT
138 *p = info->next;
139 p = &delta_list;
140 resolve_delta(type, data, size, info->delta, info->size);
141 free(info);
142 continue;
143 }
144 p = &info->next;
145 }
146}
147
148static int unpack_non_delta_entry(enum object_type kind, unsigned long size)
149{
150 void *buf = get_data(size);
cca7081a 151 const char *type;
8ee378a0 152
8ee378a0 153 switch (kind) {
8e440259
PE
154 case OBJ_COMMIT: type = commit_type; break;
155 case OBJ_TREE: type = tree_type; break;
156 case OBJ_BLOB: type = blob_type; break;
157 case OBJ_TAG: type = tag_type; break;
67e5a5ec 158 default: die("bad type %d", kind);
8ee378a0 159 }
dddafffe
LT
160 if (!dry_run)
161 write_object(buf, size, type);
67e5a5ec 162 free(buf);
8ee378a0
JH
163 return 0;
164}
165
67e5a5ec 166static int unpack_delta_entry(unsigned long delta_size)
8ee378a0 167{
67e5a5ec
LT
168 void *delta_data, *base;
169 unsigned long base_size;
8ee378a0 170 char type[20];
67e5a5ec 171 unsigned char base_sha1[20];
ee639140 172 int result;
8ee378a0 173
e702496e 174 hashcpy(base_sha1, fill(20));
67e5a5ec 175 use(20);
c4fb06c0 176
67e5a5ec 177 delta_data = get_data(delta_size);
dddafffe
LT
178 if (dry_run) {
179 free(delta_data);
180 return 0;
181 }
8ee378a0 182
c4fb06c0 183 if (!has_sha1_file(base_sha1)) {
67e5a5ec
LT
184 add_delta_to_list(base_sha1, delta_data, delta_size);
185 return 0;
8ee378a0 186 }
c4fb06c0 187 base = read_sha1_file(base_sha1, type, &base_size);
8ee378a0 188 if (!base)
c4fb06c0 189 die("failed to read delta-pack base object %s", sha1_to_hex(base_sha1));
ee639140
SV
190 result = resolve_delta(type, base, base_size, delta_data, delta_size);
191 free(base);
192 return result;
8ee378a0
JH
193}
194
d36f7b80 195static void unpack_one(unsigned nr, unsigned total)
8ee378a0 196{
01247d87 197 unsigned shift;
a733cb60 198 unsigned char *pack, c;
67e5a5ec
LT
199 unsigned long size;
200 enum object_type type;
74536958 201
67e5a5ec
LT
202 pack = fill(1);
203 c = *pack;
204 use(1);
a733cb60
LT
205 type = (c >> 4) & 7;
206 size = (c & 15);
01247d87 207 shift = 4;
a733cb60 208 while (c & 0x80) {
67e5a5ec 209 pack = fill(1);
a733cb60 210 c = *pack++;
67e5a5ec 211 use(1);
01247d87
LT
212 size += (c & 0x7f) << shift;
213 shift += 7;
a733cb60 214 }
d36f7b80
LT
215 if (!quiet) {
216 static unsigned long last_sec;
217 static unsigned last_percent;
218 struct timeval now;
cf219196 219 unsigned percentage = (nr * 100) / total;
d36f7b80
LT
220
221 gettimeofday(&now, NULL);
222 if (percentage != last_percent || now.tv_sec != last_sec) {
223 last_sec = now.tv_sec;
224 last_percent = percentage;
225 fprintf(stderr, "%4u%% (%u/%u) done\r", percentage, nr, total);
226 }
227 }
a733cb60
LT
228 switch (type) {
229 case OBJ_COMMIT:
230 case OBJ_TREE:
231 case OBJ_BLOB:
232 case OBJ_TAG:
67e5a5ec 233 unpack_non_delta_entry(type, size);
a733cb60
LT
234 return;
235 case OBJ_DELTA:
67e5a5ec 236 unpack_delta_entry(size);
a733cb60 237 return;
67e5a5ec
LT
238 default:
239 die("bad object type %d", type);
74536958
LT
240 }
241}
242
74536958
LT
243static void unpack_all(void)
244{
67e5a5ec
LT
245 int i;
246 struct pack_header *hdr = fill(sizeof(struct pack_header));
67e5a5ec
LT
247 unsigned nr_objects = ntohl(hdr->hdr_entries);
248
249 if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
250 die("bad pack file");
d60fc1c8
NP
251 if (!pack_version_ok(hdr->hdr_version))
252 die("unknown pack file version %d", ntohl(hdr->hdr_version));
67e5a5ec
LT
253 fprintf(stderr, "Unpacking %d objects\n", nr_objects);
254
255 use(sizeof(struct pack_header));
256 for (i = 0; i < nr_objects; i++)
cf219196 257 unpack_one(i+1, nr_objects);
67e5a5ec
LT
258 if (delta_list)
259 die("unresolved deltas left after unpacking");
74536958
LT
260}
261
64413630 262int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
bad50dc8
LT
263{
264 int i;
67e5a5ec 265 unsigned char sha1[20];
bad50dc8 266
8e273641 267 git_config(git_default_config);
53228a5f 268
476e8011
JH
269 quiet = !isatty(2);
270
bad50dc8
LT
271 for (i = 1 ; i < argc; i++) {
272 const char *arg = argv[i];
273
274 if (*arg == '-') {
74536958
LT
275 if (!strcmp(arg, "-n")) {
276 dry_run = 1;
277 continue;
278 }
d36f7b80
LT
279 if (!strcmp(arg, "-q")) {
280 quiet = 1;
281 continue;
282 }
bad50dc8
LT
283 usage(unpack_usage);
284 }
67e5a5ec
LT
285
286 /* We don't take any non-flag arguments now.. Maybe some day */
bad50dc8 287 usage(unpack_usage);
67e5a5ec
LT
288 }
289 SHA1_Init(&ctx);
74536958 290 unpack_all();
67e5a5ec
LT
291 SHA1_Update(&ctx, buffer, offset);
292 SHA1_Final(sha1, &ctx);
a89fccd2 293 if (hashcmp(fill(20), sha1))
67e5a5ec
LT
294 die("final sha1 did not match");
295 use(20);
296
297 /* Write the last part of the buffer to stdout */
298 while (len) {
1c15afb9
JH
299 int ret = xwrite(1, buffer + offset, len);
300 if (ret <= 0)
67e5a5ec 301 break;
67e5a5ec
LT
302 len -= ret;
303 offset += ret;
304 }
305
306 /* All done */
d36f7b80
LT
307 if (!quiet)
308 fprintf(stderr, "\n");
bad50dc8
LT
309 return 0;
310}