134 static const long v2_entry_size = 96; |
134 static const long v2_entry_size = 96; |
135 |
135 |
136 static const long format_v1 = 1; /* Internal only, could be any number */ |
136 static const long format_v1 = 1; /* Internal only, could be any number */ |
137 static const long format_v2 = 2; /* Internal only, could be any number */ |
137 static const long format_v2 = 2; /* Internal only, could be any number */ |
138 |
138 |
|
139 static const long entry_offset_high = 0; |
|
140 static const long entry_offset_offset_flags = 4; |
|
141 static const long entry_offset_comp_len = 8; |
|
142 static const long entry_offset_uncomp_len = 12; |
|
143 static const long entry_offset_base_rev = 16; |
|
144 static const long entry_offset_link_rev = 20; |
|
145 static const long entry_offset_parent_1 = 24; |
|
146 static const long entry_offset_parent_2 = 28; |
|
147 static const long entry_offset_node_id = 32; |
|
148 static const long entry_offset_sidedata_offset = 64; |
|
149 static const long entry_offset_sidedata_comp_len = 72; |
|
150 static const long entry_offset_all_comp_mode = 76; |
|
151 static const long entry_offset_padding_start = 77; |
|
152 |
139 static const char comp_mode_inline = 2; |
153 static const char comp_mode_inline = 2; |
140 static const char rank_unknown = -1; |
154 static const char rank_unknown = -1; |
141 |
155 |
142 static void raise_revlog_error(void) |
156 static void raise_revlog_error(void) |
143 { |
157 { |
204 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps, |
218 static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps, |
205 int maxrev) |
219 int maxrev) |
206 { |
220 { |
207 const char *data = index_deref(self, rev); |
221 const char *data = index_deref(self, rev); |
208 |
222 |
209 ps[0] = getbe32(data + 24); |
223 ps[0] = getbe32(data + entry_offset_parent_1); |
210 ps[1] = getbe32(data + 28); |
224 ps[1] = getbe32(data + entry_offset_parent_2); |
211 |
225 |
212 /* If index file is corrupted, ps[] may point to invalid revisions. So |
226 /* If index file is corrupted, ps[] may point to invalid revisions. So |
213 * there is a risk of buffer overflow to trust them unconditionally. */ |
227 * there is a risk of buffer overflow to trust them unconditionally. */ |
214 if (ps[0] < -1 || ps[0] > maxrev || ps[1] < -1 || ps[1] > maxrev) { |
228 if (ps[0] < -1 || ps[0] > maxrev || ps[1] < -1 || ps[1] > maxrev) { |
215 PyErr_SetString(PyExc_ValueError, "parent out of range"); |
229 PyErr_SetString(PyExc_ValueError, "parent out of range"); |
318 |
332 |
319 data = index_deref(self, pos); |
333 data = index_deref(self, pos); |
320 if (data == NULL) |
334 if (data == NULL) |
321 return NULL; |
335 return NULL; |
322 |
336 |
323 offset_flags = getbe32(data + 4); |
337 offset_flags = getbe32(data + entry_offset_offset_flags); |
324 /* |
338 /* |
325 * The first entry on-disk needs the version number masked out, |
339 * The first entry on-disk needs the version number masked out, |
326 * but this doesn't apply if entries are added to an empty index. |
340 * but this doesn't apply if entries are added to an empty index. |
327 */ |
341 */ |
328 if (self->length && pos == 0) |
342 if (self->length && pos == 0) |
329 offset_flags &= 0xFFFF; |
343 offset_flags &= 0xFFFF; |
330 else { |
344 else { |
331 uint32_t offset_high = getbe32(data); |
345 uint32_t offset_high = getbe32(data + entry_offset_high); |
332 offset_flags |= ((uint64_t)offset_high) << 32; |
346 offset_flags |= ((uint64_t)offset_high) << 32; |
333 } |
347 } |
334 |
348 |
335 comp_len = getbe32(data + 8); |
349 comp_len = getbe32(data + entry_offset_comp_len); |
336 uncomp_len = getbe32(data + 12); |
350 uncomp_len = getbe32(data + entry_offset_uncomp_len); |
337 base_rev = getbe32(data + 16); |
351 base_rev = getbe32(data + entry_offset_base_rev); |
338 link_rev = getbe32(data + 20); |
352 link_rev = getbe32(data + entry_offset_link_rev); |
339 parent_1 = getbe32(data + 24); |
353 parent_1 = getbe32(data + entry_offset_parent_1); |
340 parent_2 = getbe32(data + 28); |
354 parent_2 = getbe32(data + entry_offset_parent_2); |
341 c_node_id = data + 32; |
355 c_node_id = data + entry_offset_node_id; |
342 |
356 |
343 if (self->format_version == format_v1) { |
357 if (self->format_version == format_v1) { |
344 sidedata_offset = 0; |
358 sidedata_offset = 0; |
345 sidedata_comp_len = 0; |
359 sidedata_comp_len = 0; |
346 data_comp_mode = comp_mode_inline; |
360 data_comp_mode = comp_mode_inline; |
347 sidedata_comp_mode = comp_mode_inline; |
361 sidedata_comp_mode = comp_mode_inline; |
348 } else { |
362 } else { |
349 sidedata_offset = getbe64(data + 64); |
363 sidedata_offset = getbe64(data + entry_offset_sidedata_offset); |
350 sidedata_comp_len = getbe32(data + 72); |
364 sidedata_comp_len = |
351 data_comp_mode = data[76] & 3; |
365 getbe32(data + entry_offset_sidedata_comp_len); |
352 sidedata_comp_mode = ((data[76] >> 2) & 3); |
366 data_comp_mode = data[entry_offset_all_comp_mode] & 3; |
|
367 sidedata_comp_mode = |
|
368 ((data[entry_offset_all_comp_mode] >> 2) & 3); |
353 } |
369 } |
354 |
370 |
355 return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, |
371 return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, |
356 base_rev, link_rev, parent_1, parent_2, c_node_id, |
372 base_rev, link_rev, parent_1, parent_2, c_node_id, |
357 self->nodelen, sidedata_offset, sidedata_comp_len, |
373 self->nodelen, sidedata_offset, sidedata_comp_len, |
502 self->added = new_added; |
518 self->added = new_added; |
503 self->added_length = new_added_length; |
519 self->added_length = new_added_length; |
504 } |
520 } |
505 rev = self->length + self->new_length; |
521 rev = self->length + self->new_length; |
506 data = self->added + self->entry_size * self->new_length++; |
522 data = self->added + self->entry_size * self->new_length++; |
507 putbe32(offset_flags >> 32, data); |
523 putbe32(offset_flags >> 32, data + entry_offset_high); |
508 putbe32(offset_flags & 0xffffffffU, data + 4); |
524 putbe32(offset_flags & 0xffffffffU, data + entry_offset_offset_flags); |
509 putbe32(comp_len, data + 8); |
525 putbe32(comp_len, data + entry_offset_comp_len); |
510 putbe32(uncomp_len, data + 12); |
526 putbe32(uncomp_len, data + entry_offset_uncomp_len); |
511 putbe32(base_rev, data + 16); |
527 putbe32(base_rev, data + entry_offset_base_rev); |
512 putbe32(link_rev, data + 20); |
528 putbe32(link_rev, data + entry_offset_link_rev); |
513 putbe32(parent_1, data + 24); |
529 putbe32(parent_1, data + entry_offset_parent_1); |
514 putbe32(parent_2, data + 28); |
530 putbe32(parent_2, data + entry_offset_parent_2); |
515 memcpy(data + 32, c_node_id, c_node_id_len); |
531 memcpy(data + entry_offset_node_id, c_node_id, c_node_id_len); |
516 /* Padding since SHA-1 is only 20 bytes for now */ |
532 /* Padding since SHA-1 is only 20 bytes for now */ |
517 memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len); |
533 memset(data + entry_offset_node_id + c_node_id_len, 0, |
|
534 entry_offset_node_id - c_node_id_len); |
518 if (self->format_version == format_v2) { |
535 if (self->format_version == format_v2) { |
519 putbe64(sidedata_offset, data + 64); |
536 putbe64(sidedata_offset, data + entry_offset_sidedata_offset); |
520 putbe32(sidedata_comp_len, data + 72); |
537 putbe32(sidedata_comp_len, |
|
538 data + entry_offset_sidedata_comp_len); |
521 comp_field = data_comp_mode & 3; |
539 comp_field = data_comp_mode & 3; |
522 comp_field = comp_field | (sidedata_comp_mode & 3) << 2; |
540 comp_field = comp_field | (sidedata_comp_mode & 3) << 2; |
523 data[76] = comp_field; |
541 data[entry_offset_all_comp_mode] = comp_field; |
524 /* Padding for 96 bytes alignment */ |
542 /* Padding for 96 bytes alignment */ |
525 memset(data + 77, 0, self->entry_size - 77); |
543 memset(data + entry_offset_padding_start, 0, |
|
544 self->entry_size - entry_offset_padding_start); |
526 } |
545 } |
527 |
546 |
528 if (self->ntinitialized) |
547 if (self->ntinitialized) |
529 nt_insert(&self->nt, c_node_id, rev); |
548 nt_insert(&self->nt, c_node_id, rev); |
530 |
549 |
575 } |
594 } |
576 |
595 |
577 /* Find the newly added node, offset from the "already on-disk" length |
596 /* Find the newly added node, offset from the "already on-disk" length |
578 */ |
597 */ |
579 data = self->added + self->entry_size * (rev - self->length); |
598 data = self->added + self->entry_size * (rev - self->length); |
580 putbe64(offset_flags, data); |
599 putbe64(offset_flags, data + entry_offset_high); |
581 putbe64(sidedata_offset, data + 64); |
600 putbe64(sidedata_offset, data + entry_offset_sidedata_offset); |
582 putbe32(sidedata_comp_len, data + 72); |
601 putbe32(sidedata_comp_len, data + entry_offset_sidedata_comp_len); |
583 data[76] = (data[76] & ~(3 << 2)) | ((comp_mode & 3) << 2); |
602 data[entry_offset_all_comp_mode] = |
|
603 (data[entry_offset_all_comp_mode] & ~(3 << 2)) | |
|
604 ((comp_mode & 3) << 2); |
584 |
605 |
585 Py_RETURN_NONE; |
606 Py_RETURN_NONE; |
586 } |
607 } |
587 |
608 |
588 static PyObject *index_stats(indexObject *self) |
609 static PyObject *index_stats(indexObject *self) |
2733 Py_ssize_t len = 0; |
2754 Py_ssize_t len = 0; |
2734 |
2755 |
2735 while (pos + self->entry_size <= end && pos >= 0) { |
2756 while (pos + self->entry_size <= end && pos >= 0) { |
2736 uint32_t comp_len, sidedata_comp_len = 0; |
2757 uint32_t comp_len, sidedata_comp_len = 0; |
2737 /* 3rd element of header is length of compressed inline data */ |
2758 /* 3rd element of header is length of compressed inline data */ |
2738 comp_len = getbe32(data + pos + 8); |
2759 comp_len = getbe32(data + pos + entry_offset_comp_len); |
2739 if (self->entry_size == v2_entry_size) { |
2760 if (self->entry_size == v2_entry_size) { |
2740 sidedata_comp_len = getbe32(data + pos + 72); |
2761 sidedata_comp_len = getbe32( |
|
2762 data + pos + entry_offset_sidedata_comp_len); |
2741 } |
2763 } |
2742 incr = self->entry_size + comp_len + sidedata_comp_len; |
2764 incr = self->entry_size + comp_len + sidedata_comp_len; |
2743 if (offsets) |
2765 if (offsets) |
2744 offsets[len] = data + pos; |
2766 offsets[len] = data + pos; |
2745 len++; |
2767 len++; |