static unsigned int pack_open_windows;
static size_t peak_pack_mapped;
static size_t pack_mapped;
-static size_t page_size;
struct packed_git *packed_git;
void pack_report()
"pack_report: getpagesize() = %10" SZ_FMT "\n"
"pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n"
"pack_report: core.packedGitLimit = %10" SZ_FMT "\n",
- page_size,
+ (size_t) getpagesize(),
packed_git_window_size,
packed_git_limit);
fprintf(stderr,
}
}
-static int open_packed_git(struct packed_git *p)
+/*
+ * Do not call this directly as this leaks p->pack_fd on error return;
+ * call open_packed_git() instead.
+ */
+static int open_packed_git_1(struct packed_git *p)
{
struct stat st;
struct pack_header hdr;
return 0;
}
+static int open_packed_git(struct packed_git *p)
+{
+ if (!open_packed_git_1(p))
+ return 0;
+ if (p->pack_fd != -1) {
+ close(p->pack_fd);
+ p->pack_fd = -1;
+ }
+ return -1;
+}
+
static int in_window(struct pack_window *win, unsigned long offset)
{
/* We must promise at least 20 bytes (one hash) after the
break;
}
if (!win) {
- if (!page_size)
- page_size = getpagesize();
+ size_t window_align = packed_git_window_size / 2;
win = xcalloc(1, sizeof(*win));
- win->offset = (offset / page_size) * page_size;
+ win->offset = (offset / window_align) * window_align;
win->len = p->pack_size - win->offset;
if (win->len > packed_git_window_size)
win->len = packed_git_window_size;
/* use_pack() assures us we have [base, base + 20) available
* as a range that we can look at at. (Its actually the hash
- * size that is assurred.) With our object header encoding
+ * size that is assured.) With our object header encoding
* the maximum deflated object size is 2^137, which is just
* insane, so we know won't exceed what we have been given.
*/
}
offset = find_pack_entry_one(sha1, p);
if (offset) {
+ /*
+ * We are about to tell the caller where they can
+ * locate the requested object. We better make
+ * sure the packfile is still here and can be
+ * accessed before supplying that answer, as
+ * it may have been deleted since the index
+ * was loaded!
+ */
+ if (p->pack_fd == -1 && open_packed_git(p)) {
+ error("packfile %s cannot be accessed", p->pack_name);
+ continue;
+ }
e->offset = offset;
e->p = p;
hashcpy(e->sha1, sha1);
return unpack_entry(e.p, e.offset, type, size);
}
-void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
+/*
+ * This is meant to hold a *small* number of objects that you would
+ * want read_sha1_file() to be able to return, but yet you do not want
+ * to write them into the object store (e.g. a browse-only
+ * application).
+ */
+static struct cached_object {
+ unsigned char sha1[20];
+ const char *type;
+ void *buf;
+ unsigned long size;
+} *cached_objects;
+static int cached_object_nr, cached_object_alloc;
+
+static struct cached_object *find_cached_object(const unsigned char *sha1)
+{
+ int i;
+ struct cached_object *co = cached_objects;
+
+ for (i = 0; i < cached_object_nr; i++, co++) {
+ if (!hashcmp(co->sha1, sha1))
+ return co;
+ }
+ return NULL;
+}
+
+int pretend_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1)
+{
+ struct cached_object *co;
+
+ hash_sha1_file(buf, len, type, sha1);
+ if (has_sha1_file(sha1) || find_cached_object(sha1))
+ return 0;
+ if (cached_object_alloc <= cached_object_nr) {
+ cached_object_alloc = alloc_nr(cached_object_alloc);
+ cached_objects = xrealloc(cached_objects,
+ sizeof(*cached_objects) *
+ cached_object_alloc);
+ }
+ co = &cached_objects[cached_object_nr++];
+ co->size = len;
+ co->type = strdup(type);
+ co->buf = xmalloc(len);
+ memcpy(co->buf, buf, len);
+ hashcpy(co->sha1, sha1);
+ return 0;
+}
+
+void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
+ struct cached_object *co;
+
+ co = find_cached_object(sha1);
+ if (co) {
+ buf = xmalloc(co->size + 1);
+ memcpy(buf, co->buf, co->size);
+ ((char*)buf)[co->size] = 0;
+ strcpy(type, co->type);
+ *size = co->size;
+ return buf;
+ }
buf = read_packed_sha1(sha1, type, size);
if (buf)
if (!type)
type = blob_type;
+ /* FIXME: CRLF -> LF conversion here for blobs! We'll need the path! */
if (write_object)
ret = write_sha1_file(buf, size, type, sha1);
else