mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
fd9b1baef8
An extra field type_valid is added to carry the equivalent of OBJ_BAD in the original "type" field. in_pack_type always contains a valid type so we only need 3 bits for it. A note about accepting OBJ_NONE as "valid" type. The function read_object_list_from_stdin() can pass this value [1] and it eventually calls create_object_entry() where current code skip setting "type" field if the incoming type is zero. This does not have any bad side effects because "type" field should be memset()'d anyway. But since we also need to set type_valid now, skipping oe_set_type() leaves type_valid zero/false, which will make oe_type() return OBJ_BAD, not OBJ_NONE anymore. Apparently we do care about OBJ_NONE in prepare_pack(). This switch from OBJ_NONE to OBJ_BAD may trigger fatal: unable to get type of object ... Accepting OBJ_NONE [2] does sound wrong, but this is how it is has been for a very long time and I haven't time to dig in further. [1] See5c49c11686
(pack-objects: better check_object() performances - 2007-04-16) [2]21666f1aae
(convert object type handling from a string to a number - 2007-02-26) Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
143 lines
4.4 KiB
C
143 lines
4.4 KiB
C
#ifndef PACK_OBJECTS_H
|
|
#define PACK_OBJECTS_H
|
|
|
|
/*
|
|
* basic object info
|
|
* -----------------
|
|
* idx.oid is filled up before delta searching starts. idx.crc32 is
|
|
* only valid after the object is written out and will be used for
|
|
* generating the index. idx.offset will be both gradually set and
|
|
* used in writing phase (base objects get offset first, then deltas
|
|
* refer to them)
|
|
*
|
|
* "size" is the uncompressed object size. Compressed size of the raw
|
|
* data for an object in a pack is not stored anywhere but is computed
|
|
* and made available when reverse .idx is made.
|
|
*
|
|
* "hash" contains a path name hash which is used for sorting the
|
|
* delta list and also during delta searching. Once prepare_pack()
|
|
* returns it's no longer needed.
|
|
*
|
|
* source pack info
|
|
* ----------------
|
|
* The (in_pack, in_pack_offset) tuple contains the location of the
|
|
* object in the source pack. in_pack_header_size allows quickly
|
|
* skipping the header and going straight to the zlib stream.
|
|
*
|
|
* "type" and "in_pack_type" both describe object type. in_pack_type
|
|
* may contain a delta type, while type is always the canonical type.
|
|
*
|
|
* deltas
|
|
* ------
|
|
* Delta links (delta, delta_child and delta_sibling) are created to
|
|
* reflect that delta graph from the source pack then updated or added
|
|
* during delta searching phase when we find better deltas.
|
|
*
|
|
* delta_child and delta_sibling are last needed in
|
|
* compute_write_order(). "delta" and "delta_size" must remain valid
|
|
* at object writing phase in case the delta is not cached.
|
|
*
|
|
* If a delta is cached in memory and is compressed, delta_data points
|
|
* to the data and z_delta_size contains the compressed size. If it's
|
|
* uncompressed [1], z_delta_size must be zero. delta_size is always
|
|
* the uncompressed size and must be valid even if the delta is not
|
|
* cached.
|
|
*
|
|
* [1] during try_delta phase we don't bother with compressing because
|
|
* the delta could be quickly replaced with a better one.
|
|
*/
|
|
struct object_entry {
|
|
struct pack_idx_entry idx;
|
|
unsigned long size; /* uncompressed size */
|
|
struct packed_git *in_pack; /* already in pack */
|
|
off_t in_pack_offset;
|
|
struct object_entry *delta; /* delta base object */
|
|
struct object_entry *delta_child; /* deltified objects who bases me */
|
|
struct object_entry *delta_sibling; /* other deltified objects who
|
|
* uses the same base as me
|
|
*/
|
|
void *delta_data; /* cached delta (uncompressed) */
|
|
unsigned long delta_size; /* delta data size (uncompressed) */
|
|
unsigned long z_delta_size; /* delta data size (compressed) */
|
|
unsigned type_:TYPE_BITS;
|
|
unsigned in_pack_type:TYPE_BITS; /* could be delta */
|
|
unsigned type_valid:1;
|
|
uint32_t hash; /* name hint hash */
|
|
unsigned int in_pack_pos;
|
|
unsigned char in_pack_header_size;
|
|
unsigned preferred_base:1; /*
|
|
* we do not pack this, but is available
|
|
* to be used as the base object to delta
|
|
* objects against.
|
|
*/
|
|
unsigned no_try_delta:1;
|
|
unsigned tagged:1; /* near the very tip of refs */
|
|
unsigned filled:1; /* assigned write-order */
|
|
|
|
/*
|
|
* State flags for depth-first search used for analyzing delta cycles.
|
|
*
|
|
* The depth is measured in delta-links to the base (so if A is a delta
|
|
* against B, then A has a depth of 1, and B a depth of 0).
|
|
*/
|
|
enum {
|
|
DFS_NONE = 0,
|
|
DFS_ACTIVE,
|
|
DFS_DONE
|
|
} dfs_state;
|
|
int depth;
|
|
};
|
|
|
|
struct packing_data {
|
|
struct object_entry *objects;
|
|
uint32_t nr_objects, nr_alloc;
|
|
|
|
int32_t *index;
|
|
uint32_t index_size;
|
|
};
|
|
|
|
struct object_entry *packlist_alloc(struct packing_data *pdata,
|
|
const unsigned char *sha1,
|
|
uint32_t index_pos);
|
|
|
|
struct object_entry *packlist_find(struct packing_data *pdata,
|
|
const unsigned char *sha1,
|
|
uint32_t *index_pos);
|
|
|
|
static inline uint32_t pack_name_hash(const char *name)
|
|
{
|
|
uint32_t c, hash = 0;
|
|
|
|
if (!name)
|
|
return 0;
|
|
|
|
/*
|
|
* This effectively just creates a sortable number from the
|
|
* last sixteen non-whitespace characters. Last characters
|
|
* count "most", so things that end in ".c" sort together.
|
|
*/
|
|
while ((c = *name++) != 0) {
|
|
if (isspace(c))
|
|
continue;
|
|
hash = (hash >> 2) + (c << 24);
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
static inline enum object_type oe_type(const struct object_entry *e)
|
|
{
|
|
return e->type_valid ? e->type_ : OBJ_BAD;
|
|
}
|
|
|
|
static inline void oe_set_type(struct object_entry *e,
|
|
enum object_type type)
|
|
{
|
|
if (type >= OBJ_ANY)
|
|
BUG("OBJ_ANY cannot be set in pack-objects code");
|
|
|
|
e->type_valid = type >= OBJ_NONE;
|
|
e->type_ = (unsigned)type;
|
|
}
|
|
|
|
#endif
|