Merge branch 'jt/unify-object-info'

Code clean-ups.

* jt/unify-object-info:
  sha1_file: refactor has_sha1_file_with_flags
  sha1_file: do not access pack if unneeded
  sha1_file: teach sha1_object_info_extended more flags
  sha1_file: refactor read_object
  sha1_file: move delta base cache code up
  sha1_file: rename LOOKUP_REPLACE_OBJECT
  sha1_file: rename LOOKUP_UNKNOWN_OBJECT
  sha1_file: teach packed_object_info about typename
This commit is contained in:
Junio C Hamano 2017-07-05 13:32:57 -07:00
commit 00b7cf2379
5 changed files with 223 additions and 216 deletions

View File

@ -57,11 +57,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
struct object_context obj_context; struct object_context obj_context;
struct object_info oi = OBJECT_INFO_INIT; struct object_info oi = OBJECT_INFO_INIT;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
unsigned flags = LOOKUP_REPLACE_OBJECT; unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
const char *path = force_path; const char *path = force_path;
if (unknown_type) if (unknown_type)
flags |= LOOKUP_UNKNOWN_OBJECT; flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH, if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
oid.hash, &obj_context)) oid.hash, &obj_context))
@ -338,7 +338,8 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt,
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
if (!data->skip_object_info && if (!data->skip_object_info &&
sha1_object_info_extended(data->oid.hash, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { sha1_object_info_extended(data->oid.hash, &data->info,
OBJECT_INFO_LOOKUP_REPLACE) < 0) {
printf("%s missing\n", printf("%s missing\n",
obj_name ? obj_name : oid_to_hex(&data->oid)); obj_name ? obj_name : oid_to_hex(&data->oid));
fflush(stdout); fflush(stdout);

View File

@ -250,9 +250,11 @@ static void find_non_local_tags(struct transport *transport,
*/ */
if (ends_with(ref->name, "^{}")) { if (ends_with(ref->name, "^{}")) {
if (item && if (item &&
!has_object_file_with_flags(&ref->old_oid, HAS_SHA1_QUICK) && !has_object_file_with_flags(&ref->old_oid,
OBJECT_INFO_QUICK) &&
!will_fetch(head, ref->old_oid.hash) && !will_fetch(head, ref->old_oid.hash) &&
!has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) && !has_sha1_file_with_flags(item->util,
OBJECT_INFO_QUICK) &&
!will_fetch(head, item->util)) !will_fetch(head, item->util))
item->util = NULL; item->util = NULL;
item = NULL; item = NULL;
@ -266,7 +268,7 @@ static void find_non_local_tags(struct transport *transport,
* fetch. * fetch.
*/ */
if (item && if (item &&
!has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) && !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) &&
!will_fetch(head, item->util)) !will_fetch(head, item->util))
item->util = NULL; item->util = NULL;
@ -287,7 +289,7 @@ static void find_non_local_tags(struct transport *transport,
* checked to see if it needs fetching. * checked to see if it needs fetching.
*/ */
if (item && if (item &&
!has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) && !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) &&
!will_fetch(head, item->util)) !will_fetch(head, item->util))
item->util = NULL; item->util = NULL;

View File

@ -793,7 +793,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
if (startup_info->have_repository) { if (startup_info->have_repository) {
read_lock(); read_lock();
collision_test_needed = has_sha1_file_with_flags(oid->hash, HAS_SHA1_QUICK); collision_test_needed =
has_sha1_file_with_flags(oid->hash, OBJECT_INFO_QUICK);
read_unlock(); read_unlock();
} }

36
cache.h
View File

@ -1160,13 +1160,12 @@ extern char *xdg_config_home(const char *filename);
*/ */
extern char *xdg_cache_home(const char *filename); extern char *xdg_cache_home(const char *filename);
/* object replacement */ extern void *read_sha1_file_extended(const unsigned char *sha1,
#define LOOKUP_REPLACE_OBJECT 1 enum object_type *type,
#define LOOKUP_UNKNOWN_OBJECT 2 unsigned long *size, int lookup_replace);
extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);
static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
{ {
return read_sha1_file_extended(sha1, type, size, LOOKUP_REPLACE_OBJECT); return read_sha1_file_extended(sha1, type, size, 1);
} }
/* /*
@ -1188,13 +1187,6 @@ static inline const unsigned char *lookup_replace_object(const unsigned char *sh
return do_lookup_replace_object(sha1); return do_lookup_replace_object(sha1);
} }
static inline const unsigned char *lookup_replace_object_extended(const unsigned char *sha1, unsigned flag)
{
if (!(flag & LOOKUP_REPLACE_OBJECT))
return sha1;
return lookup_replace_object(sha1);
}
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */ /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
extern int sha1_object_info(const unsigned char *, unsigned long *); extern int sha1_object_info(const unsigned char *, unsigned long *);
extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
@ -1231,15 +1223,10 @@ int read_loose_object(const char *path,
void **contents); void **contents);
/* /*
* Return true iff we have an object named sha1, whether local or in * Convenience for sha1_object_info_extended() with a NULL struct
* an alternate object database, and whether packed or loose. This * object_info. OBJECT_INFO_SKIP_CACHED is automatically set; pass
* function does not respect replace references. * nonzero flags to also set other flags.
*
* If the QUICK flag is set, do not re-check the pack directory
* when we cannot find the object (this means we may give a false
* negative answer if another process is simultaneously repacking).
*/ */
#define HAS_SHA1_QUICK 0x1
extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags); extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags);
static inline int has_sha1_file(const unsigned char *sha1) static inline int has_sha1_file(const unsigned char *sha1)
{ {
@ -1806,6 +1793,7 @@ struct object_info {
off_t *disk_sizep; off_t *disk_sizep;
unsigned char *delta_base_sha1; unsigned char *delta_base_sha1;
struct strbuf *typename; struct strbuf *typename;
void **contentp;
/* Response */ /* Response */
enum { enum {
@ -1837,6 +1825,14 @@ struct object_info {
*/ */
#define OBJECT_INFO_INIT {NULL} #define OBJECT_INFO_INIT {NULL}
/* Invoke lookup_replace_object() on the given hash */
#define OBJECT_INFO_LOOKUP_REPLACE 1
/* Allow reading from a loose object file of unknown/bogus type */
#define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2
/* Do not check cached storage */
#define OBJECT_INFO_SKIP_CACHED 4
/* Do not retry packed storage after checking packed and loose storage */
#define OBJECT_INFO_QUICK 8
extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags); extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);
extern int packed_object_info(struct packed_git *pack, off_t offset, struct object_info *); extern int packed_object_info(struct packed_git *pack, off_t offset, struct object_info *);

View File

@ -1964,7 +1964,7 @@ static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
* we're obtaining the type using '--allow-unknown-type' * we're obtaining the type using '--allow-unknown-type'
* option. * option.
*/ */
if ((flags & LOOKUP_UNKNOWN_OBJECT) && (type < 0)) if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE) && (type < 0))
type = 0; type = 0;
else if (type < 0) else if (type < 0)
die("invalid object type"); die("invalid object type");
@ -2002,20 +2002,7 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
struct object_info oi = OBJECT_INFO_INIT; struct object_info oi = OBJECT_INFO_INIT;
oi.sizep = sizep; oi.sizep = sizep;
return parse_sha1_header_extended(hdr, &oi, LOOKUP_REPLACE_OBJECT); return parse_sha1_header_extended(hdr, &oi, 0);
}
static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
{
int ret;
git_zstream stream;
char hdr[8192];
ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)
return NULL;
return unpack_sha1_rest(&stream, hdr, *size, sha1);
} }
unsigned long get_size_from_delta(struct packed_git *p, unsigned long get_size_from_delta(struct packed_git *p,
@ -2239,107 +2226,6 @@ static enum object_type packed_to_object_type(struct packed_git *p,
goto out; goto out;
} }
int packed_object_info(struct packed_git *p, off_t obj_offset,
struct object_info *oi)
{
struct pack_window *w_curs = NULL;
unsigned long size;
off_t curpos = obj_offset;
enum object_type type;
/*
* We always get the representation type, but only convert it to
* a "real" type later if the caller is interested.
*/
type = unpack_object_header(p, &w_curs, &curpos, &size);
if (oi->sizep) {
if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
off_t tmp_pos = curpos;
off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
type, obj_offset);
if (!base_offset) {
type = OBJ_BAD;
goto out;
}
*oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
if (*oi->sizep == 0) {
type = OBJ_BAD;
goto out;
}
} else {
*oi->sizep = size;
}
}
if (oi->disk_sizep) {
struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
*oi->disk_sizep = revidx[1].offset - obj_offset;
}
if (oi->typep) {
*oi->typep = packed_to_object_type(p, obj_offset, type, &w_curs, curpos);
if (*oi->typep < 0) {
type = OBJ_BAD;
goto out;
}
}
if (oi->delta_base_sha1) {
if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
const unsigned char *base;
base = get_delta_base_sha1(p, &w_curs, curpos,
type, obj_offset);
if (!base) {
type = OBJ_BAD;
goto out;
}
hashcpy(oi->delta_base_sha1, base);
} else
hashclr(oi->delta_base_sha1);
}
out:
unuse_pack(&w_curs);
return type;
}
static void *unpack_compressed_entry(struct packed_git *p,
struct pack_window **w_curs,
off_t curpos,
unsigned long size)
{
int st;
git_zstream stream;
unsigned char *buffer, *in;
buffer = xmallocz_gently(size);
if (!buffer)
return NULL;
memset(&stream, 0, sizeof(stream));
stream.next_out = buffer;
stream.avail_out = size + 1;
git_inflate_init(&stream);
do {
in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in;
st = git_inflate(&stream, Z_FINISH);
if (!stream.avail_out)
break; /* the payload is larger than it should be */
curpos += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR);
git_inflate_end(&stream);
if ((st != Z_STREAM_END) || stream.total_out != size) {
free(buffer);
return NULL;
}
return buffer;
}
static struct hashmap delta_base_cache; static struct hashmap delta_base_cache;
static size_t delta_base_cached; static size_t delta_base_cached;
@ -2427,7 +2313,9 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
if (!ent) if (!ent)
return unpack_entry(p, base_offset, type, base_size); return unpack_entry(p, base_offset, type, base_size);
if (type)
*type = ent->type; *type = ent->type;
if (base_size)
*base_size = ent->size; *base_size = ent->size;
return xmemdupz(ent->data, ent->size); return xmemdupz(ent->data, ent->size);
} }
@ -2477,6 +2365,123 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
hashmap_add(&delta_base_cache, ent); hashmap_add(&delta_base_cache, ent);
} }
int packed_object_info(struct packed_git *p, off_t obj_offset,
struct object_info *oi)
{
struct pack_window *w_curs = NULL;
unsigned long size;
off_t curpos = obj_offset;
enum object_type type;
/*
* We always get the representation type, but only convert it to
* a "real" type later if the caller is interested.
*/
if (oi->contentp) {
*oi->contentp = cache_or_unpack_entry(p, obj_offset, oi->sizep,
&type);
if (!*oi->contentp)
type = OBJ_BAD;
} else {
type = unpack_object_header(p, &w_curs, &curpos, &size);
}
if (!oi->contentp && oi->sizep) {
if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
off_t tmp_pos = curpos;
off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
type, obj_offset);
if (!base_offset) {
type = OBJ_BAD;
goto out;
}
*oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
if (*oi->sizep == 0) {
type = OBJ_BAD;
goto out;
}
} else {
*oi->sizep = size;
}
}
if (oi->disk_sizep) {
struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
*oi->disk_sizep = revidx[1].offset - obj_offset;
}
if (oi->typep || oi->typename) {
enum object_type ptot;
ptot = packed_to_object_type(p, obj_offset, type, &w_curs,
curpos);
if (oi->typep)
*oi->typep = ptot;
if (oi->typename) {
const char *tn = typename(ptot);
if (tn)
strbuf_addstr(oi->typename, tn);
}
if (ptot < 0) {
type = OBJ_BAD;
goto out;
}
}
if (oi->delta_base_sha1) {
if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
const unsigned char *base;
base = get_delta_base_sha1(p, &w_curs, curpos,
type, obj_offset);
if (!base) {
type = OBJ_BAD;
goto out;
}
hashcpy(oi->delta_base_sha1, base);
} else
hashclr(oi->delta_base_sha1);
}
out:
unuse_pack(&w_curs);
return type;
}
static void *unpack_compressed_entry(struct packed_git *p,
struct pack_window **w_curs,
off_t curpos,
unsigned long size)
{
int st;
git_zstream stream;
unsigned char *buffer, *in;
buffer = xmallocz_gently(size);
if (!buffer)
return NULL;
memset(&stream, 0, sizeof(stream));
stream.next_out = buffer;
stream.avail_out = size + 1;
git_inflate_init(&stream);
do {
in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in;
st = git_inflate(&stream, Z_FINISH);
if (!stream.avail_out)
break; /* the payload is larger than it should be */
curpos += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR);
git_inflate_end(&stream);
if ((st != Z_STREAM_END) || stream.total_out != size) {
free(buffer);
return NULL;
}
return buffer;
}
static void *read_object(const unsigned char *sha1, enum object_type *type, static void *read_object(const unsigned char *sha1, enum object_type *type,
unsigned long *size); unsigned long *size);
@ -2670,7 +2675,9 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
free(external_base); free(external_base);
} }
if (final_type)
*final_type = type; *final_type = type;
if (final_size)
*final_size = size; *final_size = size;
unuse_pack(&w_curs); unuse_pack(&w_curs);
@ -2905,6 +2912,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
git_zstream stream; git_zstream stream;
char hdr[32]; char hdr[32];
struct strbuf hdrbuf = STRBUF_INIT; struct strbuf hdrbuf = STRBUF_INIT;
unsigned long size_scratch;
if (oi->delta_base_sha1) if (oi->delta_base_sha1)
hashclr(oi->delta_base_sha1); hashclr(oi->delta_base_sha1);
@ -2917,7 +2925,7 @@ static int sha1_loose_object_info(const unsigned char *sha1,
* return value implicitly indicates whether the * return value implicitly indicates whether the
* object even exists. * object even exists.
*/ */
if (!oi->typep && !oi->typename && !oi->sizep) { if (!oi->typep && !oi->typename && !oi->sizep && !oi->contentp) {
const char *path; const char *path;
struct stat st; struct stat st;
if (stat_sha1_file(sha1, &st, &path) < 0) if (stat_sha1_file(sha1, &st, &path) < 0)
@ -2930,9 +2938,13 @@ static int sha1_loose_object_info(const unsigned char *sha1,
map = map_sha1_file(sha1, &mapsize); map = map_sha1_file(sha1, &mapsize);
if (!map) if (!map)
return -1; return -1;
if (!oi->sizep)
oi->sizep = &size_scratch;
if (oi->disk_sizep) if (oi->disk_sizep)
*oi->disk_sizep = mapsize; *oi->disk_sizep = mapsize;
if ((flags & LOOKUP_UNKNOWN_OBJECT)) { if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) {
if (unpack_sha1_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0) if (unpack_sha1_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0)
status = error("unable to unpack %s header with --allow-unknown-type", status = error("unable to unpack %s header with --allow-unknown-type",
sha1_to_hex(sha1)); sha1_to_hex(sha1));
@ -2947,23 +2959,36 @@ static int sha1_loose_object_info(const unsigned char *sha1,
sha1_to_hex(sha1)); sha1_to_hex(sha1));
} else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0) } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
status = error("unable to parse %s header", sha1_to_hex(sha1)); status = error("unable to parse %s header", sha1_to_hex(sha1));
if (status >= 0 && oi->contentp)
*oi->contentp = unpack_sha1_rest(&stream, hdr,
*oi->sizep, sha1);
else
git_inflate_end(&stream); git_inflate_end(&stream);
munmap(map, mapsize); munmap(map, mapsize);
if (status && oi->typep) if (status && oi->typep)
*oi->typep = status; *oi->typep = status;
if (oi->sizep == &size_scratch)
oi->sizep = NULL;
strbuf_release(&hdrbuf); strbuf_release(&hdrbuf);
return (status < 0) ? status : 0; return (status < 0) ? status : 0;
} }
int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags) int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
{ {
struct cached_object *co; static struct object_info blank_oi = OBJECT_INFO_INIT;
struct pack_entry e; struct pack_entry e;
int rtype; int rtype;
enum object_type real_type; const unsigned char *real = (flags & OBJECT_INFO_LOOKUP_REPLACE) ?
const unsigned char *real = lookup_replace_object_extended(sha1, flags); lookup_replace_object(sha1) :
sha1;
co = find_cached_object(real); if (!oi)
oi = &blank_oi;
if (!(flags & OBJECT_INFO_SKIP_CACHED)) {
struct cached_object *co = find_cached_object(real);
if (co) { if (co) {
if (oi->typep) if (oi->typep)
*(oi->typep) = co->type; *(oi->typep) = co->type;
@ -2975,9 +3000,12 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
hashclr(oi->delta_base_sha1); hashclr(oi->delta_base_sha1);
if (oi->typename) if (oi->typename)
strbuf_addstr(oi->typename, typename(co->type)); strbuf_addstr(oi->typename, typename(co->type));
if (oi->contentp)
*oi->contentp = xmemdupz(co->buf, co->size);
oi->whence = OI_CACHED; oi->whence = OI_CACHED;
return 0; return 0;
} }
}
if (!find_pack_entry(real, &e)) { if (!find_pack_entry(real, &e)) {
/* Most likely it's a loose object. */ /* Most likely it's a loose object. */
@ -2987,23 +3015,25 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
} }
/* Not a loose object; someone else may have just packed it. */ /* Not a loose object; someone else may have just packed it. */
if (flags & OBJECT_INFO_QUICK) {
return -1;
} else {
reprepare_packed_git(); reprepare_packed_git();
if (!find_pack_entry(real, &e)) if (!find_pack_entry(real, &e))
return -1; return -1;
} }
}
if (oi == &blank_oi)
/* /*
* packed_object_info() does not follow the delta chain to * We know that the caller doesn't actually need the
* find out the real type, unless it is given oi->typep. * information below, so return early.
*/ */
if (oi->typename && !oi->typep) return 0;
oi->typep = &real_type;
rtype = packed_object_info(e.p, e.offset, oi); rtype = packed_object_info(e.p, e.offset, oi);
if (rtype < 0) { if (rtype < 0) {
mark_bad_packed_object(e.p, real); mark_bad_packed_object(e.p, real);
if (oi->typep == &real_type)
oi->typep = NULL;
return sha1_object_info_extended(real, oi, 0); return sha1_object_info_extended(real, oi, 0);
} else if (in_delta_base_cache(e.p, e.offset)) { } else if (in_delta_base_cache(e.p, e.offset)) {
oi->whence = OI_DBCACHED; oi->whence = OI_DBCACHED;
@ -3014,10 +3044,6 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA || oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
rtype == OBJ_OFS_DELTA); rtype == OBJ_OFS_DELTA);
} }
if (oi->typename)
strbuf_addstr(oi->typename, typename(*oi->typep));
if (oi->typep == &real_type)
oi->typep = NULL;
return 0; return 0;
} }
@ -3030,7 +3056,8 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
oi.typep = &type; oi.typep = &type;
oi.sizep = sizep; oi.sizep = sizep;
if (sha1_object_info_extended(sha1, &oi, LOOKUP_REPLACE_OBJECT) < 0) if (sha1_object_info_extended(sha1, &oi,
OBJECT_INFO_LOOKUP_REPLACE) < 0)
return -1; return -1;
return type; return type;
} }
@ -3080,28 +3107,15 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
static void *read_object(const unsigned char *sha1, enum object_type *type, static void *read_object(const unsigned char *sha1, enum object_type *type,
unsigned long *size) unsigned long *size)
{ {
unsigned long mapsize; struct object_info oi = OBJECT_INFO_INIT;
void *map, *buf; void *content;
struct cached_object *co; oi.typep = type;
oi.sizep = size;
oi.contentp = &content;
co = find_cached_object(sha1); if (sha1_object_info_extended(sha1, &oi, 0) < 0)
if (co) { return NULL;
*type = co->type; return content;
*size = co->size;
return xmemdupz(co->buf, co->size);
}
buf = read_packed_sha1(sha1, type, size);
if (buf)
return buf;
map = map_sha1_file(sha1, &mapsize);
if (map) {
buf = unpack_sha1_file(map, mapsize, type, size, sha1);
munmap(map, mapsize);
return buf;
}
reprepare_packed_git();
return read_packed_sha1(sha1, type, size);
} }
/* /*
@ -3112,13 +3126,14 @@ static void *read_object(const unsigned char *sha1, enum object_type *type,
void *read_sha1_file_extended(const unsigned char *sha1, void *read_sha1_file_extended(const unsigned char *sha1,
enum object_type *type, enum object_type *type,
unsigned long *size, unsigned long *size,
unsigned flag) int lookup_replace)
{ {
void *data; void *data;
const struct packed_git *p; const struct packed_git *p;
const char *path; const char *path;
struct stat st; struct stat st;
const unsigned char *repl = lookup_replace_object_extended(sha1, flag); const unsigned char *repl = lookup_replace ? lookup_replace_object(sha1)
: sha1;
errno = 0; errno = 0;
data = read_object(repl, type, size); data = read_object(repl, type, size);
@ -3479,18 +3494,10 @@ int has_sha1_pack(const unsigned char *sha1)
int has_sha1_file_with_flags(const unsigned char *sha1, int flags) int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
{ {
struct pack_entry e;
if (!startup_info->have_repository) if (!startup_info->have_repository)
return 0; return 0;
if (find_pack_entry(sha1, &e)) return sha1_object_info_extended(sha1, NULL,
return 1; flags | OBJECT_INFO_SKIP_CACHED) >= 0;
if (has_loose_object(sha1))
return 1;
if (flags & HAS_SHA1_QUICK)
return 0;
reprepare_packed_git();
return find_pack_entry(sha1, &e);
} }
int has_object_file(const struct object_id *oid) int has_object_file(const struct object_id *oid)