die("pack has bad object at offset %lu: %s", offset, buf);
}
+static void free_base_data(struct base_data *c)
+{
+ if (c->data) {
+ free(c->data);
+ c->data = NULL;
+ base_cache_used -= c->size;
+ }
+}
+
static void prune_base_data(struct base_data *retain)
{
struct base_data *b = base_cache;
for (b = base_cache;
base_cache_used > delta_base_cache_limit && b;
b = b->child) {
- if (b->data && b != retain) {
- free(b->data);
- b->data = NULL;
- base_cache_used -= b->size;
- }
+ if (b->data && b != retain)
+ free_base_data(b);
}
}
base->child = NULL;
else
base_cache = NULL;
- if (c->data) {
- free(c->data);
- base_cache_used -= c->size;
- }
+ free_base_data(c);
}
static void *unpack_entry_data(unsigned long offset, unsigned long size)
base_offset = (base_offset << 7) + (c & 127);
}
delta_base->offset = obj->idx.offset - base_offset;
- if (delta_base->offset >= obj->idx.offset)
+ if (delta_base->offset <= 0 || delta_base->offset >= obj->idx.offset)
bad_object(obj->idx.offset, "delta base offset is out of bound");
break;
case OBJ_COMMIT:
return -first-1;
}
-static int find_delta_children(const union delta_base *base,
- int *first_index, int *last_index)
+static void find_delta_children(const union delta_base *base,
+ int *first_index, int *last_index)
{
int first = find_delta(base);
int last = first;
int end = nr_deltas - 1;
- if (first < 0)
- return -1;
+ if (first < 0) {
+ *first_index = 0;
+ *last_index = -1;
+ return;
+ }
while (first > 0 && !memcmp(&deltas[first - 1].base, base, UNION_BASE_SZ))
--first;
while (last < end && !memcmp(&deltas[last + 1].base, base, UNION_BASE_SZ))
++last;
*first_index = first;
*last_index = last;
- return 0;
}
static void sha1_object(const void *data, unsigned long size,
static void resolve_delta(struct object_entry *delta_obj,
struct base_data *base, struct base_data *result)
{
- void *delta_data;
- unsigned long delta_size;
+ void *base_data, *delta_data;
- delta_obj->real_type = base->obj->type;
+ delta_obj->real_type = base->obj->real_type;
delta_data = get_data_from_pack(delta_obj);
- delta_size = delta_obj->size;
+ base_data = get_base_data(base);
result->obj = delta_obj;
- result->data = patch_delta(get_base_data(base), base->obj->size,
- delta_data, delta_size, &result->size);
+ result->data = patch_delta(base_data, base->size,
+ delta_data, delta_obj->size, &result->size);
free(delta_data);
if (!result->data)
bad_object(delta_obj->idx.offset, "failed to apply delta");
static void find_unresolved_deltas(struct base_data *base,
struct base_data *prev_base)
{
- int i, ref, ref_first, ref_last, ofs, ofs_first, ofs_last;
+ int i, ref_first, ref_last, ofs_first, ofs_last;
/*
* This is a recursive function. Those brackets should help reducing
union delta_base base_spec;
hashcpy(base_spec.sha1, base->obj->idx.sha1);
- ref = !find_delta_children(&base_spec, &ref_first, &ref_last);
+ find_delta_children(&base_spec, &ref_first, &ref_last);
memset(&base_spec, 0, sizeof(base_spec));
base_spec.offset = base->obj->idx.offset;
- ofs = !find_delta_children(&base_spec, &ofs_first, &ofs_last);
+ find_delta_children(&base_spec, &ofs_first, &ofs_last);
}
- if (!ref && !ofs)
+ if (ref_last == -1 && ofs_last == -1) {
+ free(base->data);
return;
+ }
link_base_data(prev_base, base);
- if (ref) {
- for (i = ref_first; i <= ref_last; i++) {
- struct object_entry *child = objects + deltas[i].obj_no;
- if (child->real_type == OBJ_REF_DELTA) {
- struct base_data result;
- resolve_delta(child, base, &result);
- find_unresolved_deltas(&result, base);
- }
+ for (i = ref_first; i <= ref_last; i++) {
+ struct object_entry *child = objects + deltas[i].obj_no;
+ if (child->real_type == OBJ_REF_DELTA) {
+ struct base_data result;
+ resolve_delta(child, base, &result);
+ if (i == ref_last && ofs_last == -1)
+ free_base_data(base);
+ find_unresolved_deltas(&result, base);
}
}
- if (ofs) {
- for (i = ofs_first; i <= ofs_last; i++) {
- struct object_entry *child = objects + deltas[i].obj_no;
- if (child->real_type == OBJ_OFS_DELTA) {
- struct base_data result;
- resolve_delta(child, base, &result);
- find_unresolved_deltas(&result, base);
- }
+ for (i = ofs_first; i <= ofs_last; i++) {
+ struct object_entry *child = objects + deltas[i].obj_no;
+ if (child->real_type == OBJ_OFS_DELTA) {
+ struct base_data result;
+ resolve_delta(child, base, &result);
+ if (i == ofs_last)
+ free_base_data(base);
+ find_unresolved_deltas(&result, base);
}
}
err = close(output_fd);
if (err)
die("error while closing pack file: %s", strerror(errno));
- chmod(curr_pack_name, 0444);
}
if (keep_msg) {
if (move_temp_to_file(curr_pack_name, final_pack_name))
die("cannot store pack file");
}
+ if (from_stdin)
+ chmod(final_pack_name, 0444);
- chmod(curr_index_name, 0444);
if (final_index_name != curr_index_name) {
if (!final_index_name) {
snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
if (move_temp_to_file(curr_index_name, final_index_name))
die("cannot store index file");
}
+ chmod(final_index_name, 0444);
if (!from_stdin) {
printf("%s\n", sha1_to_hex(sha1));
char *index_name_buf = NULL, *keep_name_buf = NULL;
struct pack_idx_entry **idx_objects;
unsigned char pack_sha1[20];
- int nongit = 0;
- setup_git_directory_gently(&nongit);
- git_config(git_index_pack_config, NULL);
+ /*
+ * We wish to read the repository's config file if any, and
+ * for that it is necessary to call setup_git_directory_gently().
+ * However if the cwd was inside .git/objects/pack/ then we need
+ * to go back there or all the pack name arguments will be wrong.
+ * And in that case we cannot rely on any prefix returned by
+ * setup_git_directory_gently() either.
+ */
+ {
+ char cwd[PATH_MAX+1];
+ int nongit;
+
+ if (!getcwd(cwd, sizeof(cwd)-1))
+ die("Unable to get current working directory");
+ setup_git_directory_gently(&nongit);
+ git_config(git_index_pack_config, NULL);
+ if (chdir(cwd))
+ die("Cannot come back to cwd");
+ }
for (i = 1; i < argc; i++) {
char *arg = argv[i];