static open_method_decl(pack_non_delta) { struct pack_window *window; enum object_type in_pack_type; st->u.in_pack.pack = oi->u.packed.pack; st->u.in_pack.pos = oi->u.packed.offset; window = NULL; in_pack_type = unpack_object_header(st->u.in_pack.pack, &window, &st->u.in_pack.pos, &st->size); unuse_pack(&window); switch (in_pack_type) { default: return -1; /* we do not do deltas for now */ case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: case OBJ_TAG: break; } st->z_state = z_unused; st->vtbl = &pack_non_delta_vtbl; return 0; }
static read_method_decl(pack_non_delta) { size_t total_read = 0; switch (st->z_state) { case z_unused: memset(&st->z, 0, sizeof(st->z)); git_inflate_init(&st->z); st->z_state = z_used; break; case z_done: return 0; case z_error: return -1; case z_used: break; } while (total_read < sz) { int status; struct pack_window *window = NULL; unsigned char *mapped; mapped = use_pack(st->u.in_pack.pack, &window, st->u.in_pack.pos, &st->z.avail_in); st->z.next_out = (unsigned char *)buf + total_read; st->z.avail_out = sz - total_read; st->z.next_in = mapped; status = git_inflate(&st->z, Z_FINISH); st->u.in_pack.pos += st->z.next_in - mapped; total_read = st->z.next_out - (unsigned char *)buf; unuse_pack(&window); if (status == Z_STREAM_END) { git_inflate_end(&st->z); st->z_state = z_done; break; } if (status != Z_OK && status != Z_BUF_ERROR) { git_inflate_end(&st->z); st->z_state = z_error; return -1; } } return total_read; }
void fast_import_sha1write(struct sha1file *f, const void *buf, unsigned int count) { if (!pack_win) { pack_win = xcalloc(1, sizeof(*pack_data->windows)); pack_win->offset = 0; pack_win->len = 20; pack_win->base = xmalloc(packed_git_window_size); pack_win->next = NULL; } /* pack_data is not set the first time sha1write is called */ if (pack_data && !pack_data->windows) { pack_data->windows = pack_win; pack_data->pack_size = pack_win->len; } sha1write(f, buf, count); pack_win->last_used = -1; /* always last used */ pack_win->inuse_cnt = -1; if (pack_data) pack_data->pack_size += count; if (packed_git_window_size - pack_win->len >= count) { memcpy(pack_win->base + pack_win->len - 20, buf, count); pack_win->len += count; } else { /* We're closing the window, so we don't actually need * to copy the beginning of the data, only what will * remain in the new window. */ pack_win->offset += (((off_t) pack_win->len - 20 + count) / packed_git_window_size) * packed_git_window_size; pack_win->len = count % packed_git_window_size - (packed_git_window_size - pack_win->len); memcpy(pack_win->base, buf + count - pack_win->len + 20, pack_win->len - 20); /* Ensure a pack window on the data before that, otherwise, * use_pack() may try to create a window that overlaps with * this one, and that won't work because it won't be complete. */ sha1flush(f); if (prev_win) unuse_pack(&prev_win); use_pack(pack_data, &prev_win, pack_win->offset - packed_git_window_size, NULL); } }
static void cleanup() { if (!initialized) return; if (prev_win) unuse_pack(&prev_win); if (pack_data) { struct pack_window *win, *prev; for (prev = NULL, win = pack_data->windows; win; prev = win, win = win->next) { if (win != pack_win) continue; if (prev) prev->next = win->next; else pack_data->windows = win->next; break; } } if (pack_win) { free(pack_win->base); free(pack_win); } end_packfile(); if (!require_explicit_termination) dump_branches(); unkeep_all_packs(); initialized = 0; pack_report(); }