Raw
1 #define USE_THE_REPOSITORY_VARIABLE
2
3 #include "test-tool.h"
4 #include "git-compat-util.h"
5 #include "delta.h"
6 #include "git-zlib.h"
7 #include "hash.h"
8 #include "hex.h"
9 #include "pack.h"
10 #include "pack-objects.h"
11 #include "parse-options.h"
12 #include "setup.h"
13 #include "strbuf.h"
14 #include "string-list.h"
15
16 static const char *usage_str[] = {
17 "test-tool pack-deltas --num-objects <num-objects>",
18 NULL
19 };
20
21 static unsigned long do_compress(void **pptr, unsigned long size)
22 {
23 git_zstream stream;
24 void *in, *out;
25 unsigned long maxsize;
26
27 git_deflate_init(&stream, 1);
28 maxsize = git_deflate_bound(&stream, size);
29
30 in = *pptr;
31 out = xmalloc(maxsize);
32 *pptr = out;
33
34 stream.next_in = in;
35 stream.avail_in = size;
36 stream.next_out = out;
37 stream.avail_out = maxsize;
38 while (git_deflate(&stream, Z_FINISH) == Z_OK)
39 ; /* nothing */
40 git_deflate_end(&stream);
41
42 free(in);
43 return stream.total_out;
44 }
45
46 static void write_ref_delta(struct hashfile *f,
47 struct object_id *oid,
48 struct object_id *base)
49 {
50 unsigned char header[MAX_PACK_OBJECT_HEADER];
51 unsigned long size, base_size, delta_size, compressed_size, hdrlen;
52 enum object_type type;
53 void *base_buf, *delta_buf;
54 void *buf = odb_read_object(the_repository->objects,
55 oid, &type, &size);
56
57 if (!buf)
58 die("unable to read %s", oid_to_hex(oid));
59
60 base_buf = odb_read_object(the_repository->objects,
61 base, &type, &base_size);
62
63 if (!base_buf)
64 die("unable to read %s", oid_to_hex(base));
65
66 delta_buf = diff_delta(base_buf, base_size,
67 buf, size, &delta_size, 0);
68
69 compressed_size = do_compress(&delta_buf, delta_size);
70
71 hdrlen = encode_in_pack_object_header(header, sizeof(header),
72 OBJ_REF_DELTA, delta_size);
73 hashwrite(f, header, hdrlen);
74 hashwrite(f, base->hash, the_repository->hash_algo->rawsz);
75 hashwrite(f, delta_buf, compressed_size);
76
77 free(buf);
78 free(base_buf);
79 free(delta_buf);
80 }
81
82 int cmd__pack_deltas(int argc, const char **argv)
83 {
84 int num_objects = -1;
85 struct hashfile *f;
86 struct strbuf line = STRBUF_INIT;
87 struct option options[] = {
88 OPT_INTEGER('n', "num-objects", &num_objects, N_("the number of objects to write")),
89 OPT_END()
90 };
91
92 argc = parse_options(argc, argv, NULL,
93 options, usage_str, 0);
94
95 if (argc || num_objects < 0)
96 usage_with_options(usage_str, options);
97
98 setup_git_directory(the_repository);
99
100 f = hashfd(the_repository->hash_algo, 1, "<stdout>");
101 write_pack_header(f, num_objects);
102
103 /* Read each line from stdin into 'line' */
104 while (strbuf_getline_lf(&line, stdin) != EOF) {
105 const char *type_str, *content_oid_str, *base_oid_str = NULL;
106 struct object_id content_oid, base_oid;
107 struct string_list items = STRING_LIST_INIT_NODUP;
108 /*
109 * Tokenize into two or three parts:
110 * 1. REF_DELTA, OFS_DELTA, or FULL.
111 * 2. The object ID for the content object.
112 * 3. The object ID for the base object (optional).
113 */
114 if (string_list_split_in_place(&items, line.buf, " ", 3) < 0)
115 die("invalid input format: %s", line.buf);
116
117 if (items.nr < 2)
118 die("invalid input format: %s", line.buf);
119
120 type_str = items.items[0].string;
121 content_oid_str = items.items[1].string;
122
123 if (get_oid_hex(content_oid_str, &content_oid))
124 die("invalid object: %s", content_oid_str);
125 if (items.nr >= 3) {
126 base_oid_str = items.items[2].string;
127 if (get_oid_hex(base_oid_str, &base_oid))
128 die("invalid object: %s", base_oid_str);
129 }
130 string_list_clear(&items, 0);
131
132 if (!strcmp(type_str, "REF_DELTA"))
133 write_ref_delta(f, &content_oid, &base_oid);
134 else if (!strcmp(type_str, "OFS_DELTA"))
135 die("OFS_DELTA not implemented");
136 else if (!strcmp(type_str, "FULL"))
137 die("FULL not implemented");
138 else
139 die("unknown pack type: %s", type_str);
140 }
141
142 finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK,
143 CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);
144 strbuf_release(&line);
145 return 0;
146 }