5 static const char pack_usage
[] = "git-pack-objects [--window=N] base-name < object-list";
12 OBJ_DELTA
// NOTE! This is _not_ the same as a "delta" object in the filesystem
16 unsigned char sha1
[20];
21 enum object_type type
;
22 unsigned long delta_size
;
23 struct object_entry
*delta
;
26 static struct object_entry
**sorted_by_sha
, **sorted_by_type
;
27 static struct object_entry
*objects
= NULL
;
28 static int nr_objects
= 0, nr_alloc
= 0;
29 static int delta_window
= 10;
30 static const char *base_name
;
35 unsigned char buffer
[8192];
38 static FILE *create_file(const char *suffix
)
40 static char filename
[PATH_MAX
];
43 len
= snprintf(filename
, PATH_MAX
, "%s.%s", base_name
, suffix
);
45 die("you wascally wabbit, you");
46 return fopen(filename
, "w");
49 static unsigned long fwrite_compressed(void *in
, unsigned long size
, FILE *f
)
52 unsigned long maxsize
;
55 memset(&stream
, 0, sizeof(stream
));
56 deflateInit(&stream
, Z_DEFAULT_COMPRESSION
);
57 maxsize
= deflateBound(&stream
, size
);
58 out
= xmalloc(maxsize
);
62 stream
.avail_in
= size
;
64 stream
.next_out
= out
;
65 stream
.avail_out
= maxsize
;
67 while (deflate(&stream
, Z_FINISH
) == Z_OK
)
71 size
= stream
.total_out
;
72 fwrite(out
, size
, 1, f
);
77 static void *delta_against(void *buf
, unsigned long size
, struct object_entry
*entry
)
79 unsigned long othersize
, delta_size
;
81 void *otherbuf
= read_sha1_file(entry
->delta
->sha1
, type
, &othersize
);
85 die("unable to read %s", sha1_to_hex(entry
->delta
->sha1
));
86 delta_buf
= diff_delta(buf
, size
, otherbuf
, othersize
, &delta_size
);
87 if (delta_size
!= entry
->delta_size
)
88 die("delta size changed");
94 static unsigned long write_object(FILE *f
, struct object_entry
*entry
)
98 void *buf
= read_sha1_file(entry
->sha1
, type
, &size
);
100 unsigned hdrlen
, datalen
;
103 die("unable to read %s", sha1_to_hex(entry
->sha1
));
104 if (size
!= entry
->size
)
105 die("object %s size inconsistency (%lu vs %lu)", sha1_to_hex(entry
->sha1
), size
, entry
->size
);
108 * The object header is a byte of 'type' followed by four bytes of
109 * length, except for deltas that has the 20 bytes of delta sha
112 header
[0] = ".CTB"[entry
->type
];
113 datalen
= htonl(size
);
114 memcpy(header
+1, &datalen
, 4);
118 memcpy(header
+1, entry
->delta
, 20);
119 buf
= delta_against(buf
, size
, entry
);
120 size
= entry
->delta_size
;
123 fwrite(header
, hdrlen
, 1, f
);
124 datalen
= fwrite_compressed(buf
, size
, f
);
126 return hdrlen
+ datalen
;
129 static void write_pack_file(void)
132 FILE *f
= create_file("pack");
133 unsigned long offset
= 0;
136 for (i
= 0; i
< nr_objects
; i
++) {
137 struct object_entry
*entry
= objects
+ i
;
138 entry
->offset
= offset
;
139 offset
+= write_object(f
, entry
);
146 static void write_index_file(void)
149 FILE *f
= create_file("idx");
150 struct object_entry
**list
= sorted_by_sha
;
151 struct object_entry
**last
= list
+ nr_objects
;
152 unsigned int array
[256];
155 * Write the first-level table (the list is sorted,
156 * but we use a 256-entry lookup to be able to avoid
157 * having to do eight extra binary search iterations)
159 for (i
= 0; i
< 256; i
++) {
160 struct object_entry
**next
= list
;
161 while (next
< last
) {
162 struct object_entry
*entry
= *next
;
163 if (entry
->sha1
[0] != i
)
167 array
[i
] = htonl(next
- sorted_by_sha
);
170 fwrite(array
, 256, sizeof(int), f
);
173 * Write the actual SHA1 entries..
175 list
= sorted_by_sha
;
176 for (i
= 0; i
< nr_objects
; i
++) {
177 struct object_entry
*entry
= *list
++;
178 unsigned int offset
= htonl(entry
->offset
);
179 fwrite(&offset
, 4, 1, f
);
180 fwrite(entry
->sha1
, 20, 1, f
);
185 static void add_object_entry(unsigned char *sha1
)
187 unsigned int idx
= nr_objects
;
188 struct object_entry
*entry
;
190 if (idx
>= nr_alloc
) {
191 unsigned int needed
= (idx
+ 1024) * 3 / 2;
192 objects
= xrealloc(objects
, needed
* sizeof(*entry
));
195 entry
= objects
+ idx
;
196 memset(entry
, 0, sizeof(*entry
));
197 memcpy(entry
->sha1
, sha1
, 20);
201 static void check_object(struct object_entry
*entry
)
205 unsigned long mapsize
;
209 map
= map_sha1_file(entry
->sha1
, &mapsize
);
211 die("unable to map %s", sha1_to_hex(entry
->sha1
));
212 if (unpack_sha1_header(&stream
, map
, mapsize
, buffer
, sizeof(buffer
)) < 0)
213 die("unable to unpack %s header", sha1_to_hex(entry
->sha1
));
214 munmap(map
, mapsize
);
215 if (parse_sha1_header(buffer
, type
, &entry
->size
) < 0)
216 die("unable to parse %s header", sha1_to_hex(entry
->sha1
));
217 if (!strcmp(type
, "commit")) {
218 entry
->type
= OBJ_COMMIT
;
219 } else if (!strcmp(type
, "tree")) {
220 entry
->type
= OBJ_TREE
;
221 } else if (!strcmp(type
, "blob")) {
222 entry
->type
= OBJ_BLOB
;
224 die("unable to pack object %s of type %s", sha1_to_hex(entry
->sha1
), type
);
227 static void get_object_details(void)
230 struct object_entry
*entry
= objects
;
232 for (i
= 0; i
< nr_objects
; i
++)
233 check_object(entry
++);
236 typedef int (*entry_sort_t
)(const struct object_entry
*, const struct object_entry
*);
238 static entry_sort_t current_sort
;
240 static int sort_comparator(const void *_a
, const void *_b
)
242 struct object_entry
*a
= *(struct object_entry
**)_a
;
243 struct object_entry
*b
= *(struct object_entry
**)_b
;
244 return current_sort(a
,b
);
247 static struct object_entry
**create_sorted_list(entry_sort_t sort
)
249 struct object_entry
**list
= xmalloc(nr_objects
* sizeof(struct object_entry
*));
252 for (i
= 0; i
< nr_objects
; i
++)
253 list
[i
] = objects
+ i
;
255 qsort(list
, nr_objects
, sizeof(struct object_entry
*), sort_comparator
);
259 static int sha1_sort(const struct object_entry
*a
, const struct object_entry
*b
)
261 return memcmp(a
->sha1
, b
->sha1
, 20);
264 static int type_size_sort(const struct object_entry
*a
, const struct object_entry
*b
)
266 if (a
->type
< b
->type
)
268 if (a
->type
> b
->type
)
270 if (a
->size
< b
->size
)
272 if (a
->size
> b
->size
)
274 return a
< b
? -1 : (a
> b
);
278 struct object_entry
*entry
;
283 * We search for deltas in a list sorted by type and by size, and
284 * walk the "old" chain backwards in the list, so if the type
285 * has changed or the size difference is too big, there's no point
286 * in even continuing the walk, since the other old objects are
287 * going to be even smaller or of a different type. So return -1
288 * once we determine that there's no point even trying.
290 static int try_delta(struct unpacked
*cur
, struct unpacked
*old
)
292 struct object_entry
*cur_entry
= cur
->entry
;
293 struct object_entry
*old_entry
= old
->entry
;
294 unsigned long size
, oldsize
, delta_size
;
297 /* Don't bother doing diffs between different types */
298 if (cur_entry
->type
!= old_entry
->type
)
301 /* Size is guaranteed to be larger than or equal to oldsize */
302 size
= cur_entry
->size
;
303 oldsize
= old_entry
->size
;
304 if (size
- oldsize
> oldsize
/ 4)
310 * We always delta from the bigger to the smaller, since that's
311 * more space-efficient (deletes don't have to say _what_ they
314 delta_buf
= diff_delta(cur
->data
, size
, old
->data
, oldsize
, &delta_size
);
316 die("unable to create delta");
317 if (delta_size
+ 20 < size
/ 2) {
318 if (!cur_entry
->delta
|| cur_entry
->delta_size
> delta_size
) {
319 cur_entry
->delta
= old_entry
;
320 cur_entry
->delta_size
= delta_size
;
326 static void find_deltas(struct object_entry
**list
, int window
)
329 unsigned int array_size
= window
* sizeof(struct unpacked
);
330 struct unpacked
*array
= xmalloc(array_size
);
332 memset(array
, 0, array_size
);
333 for (i
= 0; i
< nr_objects
; i
++) {
334 unsigned int idx
= i
% window
;
335 struct object_entry
*entry
= list
[i
];
336 struct unpacked
*n
= array
+ idx
;
343 n
->data
= read_sha1_file(entry
->sha1
, type
, &size
);
344 if (size
!= entry
->size
)
345 die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(entry
->sha1
), size
, entry
->size
);
346 for (j
= 0; j
< window
; j
++) {
347 unsigned int other_idx
= idx
- 1 - j
;
351 m
= array
+ other_idx
;
354 if (try_delta(n
, m
) < 0)
360 int main(int argc
, char **argv
)
365 for (i
= 1; i
< argc
; i
++) {
366 const char *arg
= argv
[i
];
369 if (!strncmp("--window=", arg
, 9)) {
371 delta_window
= strtoul(arg
+9, &end
, 0);
386 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
387 unsigned char sha1
[20];
388 if (get_sha1_hex(line
, sha1
))
389 die("expected sha1, got garbage");
390 add_object_entry(sha1
);
392 get_object_details();
394 printf("Packing %d objects\n", nr_objects
);
396 sorted_by_sha
= create_sorted_list(sha1_sort
);
397 sorted_by_type
= create_sorted_list(type_size_sort
);
399 find_deltas(sorted_by_type
, delta_window
);