#include "tag.h"
#include "tree.h"
#include "refs.h"
+#include "pack-revindex.h"
#ifndef O_NOATIME
#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
#ifdef NO_C99_FORMAT
#define SZ_FMT "lu"
+static unsigned long sz_fmt(size_t s) { return (unsigned long)s; }
#else
#define SZ_FMT "zu"
+static size_t sz_fmt(size_t s) { return s; }
#endif
const unsigned char null_sha1[20];
char *pos = path;
struct stat st;
- if (*pos == '/')
+ if (is_absolute_path(path))
pos++;
while (pos) {
/*
* NOTE! This returns a statically allocated buffer, so you have to be
- * careful about using it. Do a "xstrdup()" if you need to save the
+ * careful about using it. Do an "xstrdup()" if you need to save the
* filename.
*
* Also note that this returns the location for creating. Reading
int entlen = pfxlen + 43;
int base_len = -1;
- if (*entry != '/' && relative_base) {
+ if (!is_absolute_path(entry) && relative_base) {
/* Relative alt-odb */
if (base_len < 0)
base_len = strlen(relative_base) + 1;
}
ent = xmalloc(sizeof(*ent) + entlen);
- if (*entry != '/' && relative_base) {
+ if (!is_absolute_path(entry) && relative_base) {
memcpy(ent->base, relative_base, base_len - 1);
ent->base[base_len - 1] = '/';
memcpy(ent->base + base_len, entry, len);
while (cp < ep && *cp != sep)
cp++;
if (last != cp) {
- if ((*last != '/') && depth) {
+ if (!is_absolute_path(last) && depth) {
error("%s: ignoring relative alternate object store %s",
relative_base, last);
} else {
"pack_report: getpagesize() = %10" SZ_FMT "\n"
"pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n"
"pack_report: core.packedGitLimit = %10" SZ_FMT "\n",
- (size_t) getpagesize(),
- packed_git_window_size,
- packed_git_limit);
+ sz_fmt(getpagesize()),
+ sz_fmt(packed_git_window_size),
+ sz_fmt(packed_git_limit));
fprintf(stderr,
"pack_report: pack_used_ctr = %10u\n"
"pack_report: pack_mmap_calls = %10u\n"
pack_used_ctr,
pack_mmap_calls,
pack_open_windows, peak_pack_open_windows,
- pack_mapped, peak_pack_mapped);
+ sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
}
static int check_packed_git_idx(const char *path, struct packed_git *p)
munmap(idx_map, idx_size);
return error("wrong index v2 file size in %s", path);
}
- if (idx_size != min_size) {
- /* make sure we can deal with large pack offsets */
- off_t x = 0x7fffffffUL, y = 0xffffffffUL;
- if (x > (x + 1) || y > (y + 1)) {
- munmap(idx_map, idx_size);
- return error("pack too large for current definition of off_t in %s", path);
- }
+ if (idx_size != min_size &&
+ /*
+ * make sure we can deal with large pack offsets.
+ * 31-bit signed offset won't be enough, neither
+ * 32-bit unsigned one will be.
+ */
+ (sizeof(off_t) <= 4)) {
+ munmap(idx_map, idx_size);
+ return error("pack too large for current definition of off_t in %s", path);
}
}
; /* nothing */
}
+void close_pack_windows(struct packed_git *p)
+{
+ while (p->windows) {
+ struct pack_window *w = p->windows;
+
+ if (w->inuse_cnt)
+ die("pack '%s' still has open windows to it",
+ p->pack_name);
+ munmap(w->base, w->len);
+ pack_mapped -= w->len;
+ pack_open_windows--;
+ p->windows = w->next;
+ free(w);
+ }
+}
+
void unuse_pack(struct pack_window **w_cursor)
{
struct pack_window *w = *w_cursor;
unsigned long dummy;
unsigned char *next_sha1;
enum object_type type;
+ struct revindex_entry *revidx;
*delta_chain_length = 0;
curpos = obj_offset;
type = unpack_object_header(p, &w_curs, &curpos, size);
+ revidx = find_pack_revindex(p, obj_offset);
+ *store_size = revidx[1].offset - obj_offset;
+
for (;;) {
switch (type) {
default:
case OBJ_TREE:
case OBJ_BLOB:
case OBJ_TAG:
- *store_size = 0; /* notyet */
unuse_pack(&w_curs);
return typename(type);
case OBJ_OFS_DELTA:
obj_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
if (*delta_chain_length == 0) {
- /* TODO: find base_sha1 as pointed by curpos */
- hashclr(base_sha1);
+ revidx = find_pack_revindex(p, obj_offset);
+ hashcpy(base_sha1, nth_packed_object_sha1(p, revidx->nr));
}
break;
case OBJ_REF_DELTA:
} *cached_objects;
static int cached_object_nr, cached_object_alloc;
+static struct cached_object empty_tree = {
+ /* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */
+ "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60"
+ "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04",
+ OBJ_TREE,
+ "",
+ 0
+};
+
static struct cached_object *find_cached_object(const unsigned char *sha1)
{
int i;
if (!hashcmp(co->sha1, sha1))
return co;
}
+ if (!hashcmp(sha1, empty_tree.sha1))
+ return &empty_tree;
return NULL;
}
}
ref_length = strlen(ref_type);
- if (memcmp(buffer, ref_type, ref_length) ||
+ if (ref_length + 40 > isize ||
+ memcmp(buffer, ref_type, ref_length) ||
get_sha1_hex((char *) buffer + ref_length, actual_sha1)) {
free(buffer);
return NULL;
if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) {
struct strbuf nbuf;
strbuf_init(&nbuf, 0);
- if (convert_to_git(path, buf, size, &nbuf)) {
+ if (convert_to_git(path, buf, size, &nbuf,
+ write_object ? safe_crlf : 0)) {
munmap(buf, size);
buf = strbuf_detach(&nbuf, &size);
re_allocated = 1;