diff options
Diffstat (limited to 'object-file.h')
-rw-r--r-- | object-file.h | 205 |
1 files changed, 157 insertions, 48 deletions
diff --git a/object-file.h b/object-file.h index 81b30d269c..6f41142452 100644 --- a/object-file.h +++ b/object-file.h @@ -3,6 +3,7 @@ #include "git-zlib.h" #include "object.h" +#include "object-store.h" struct index_state; @@ -14,50 +15,113 @@ struct index_state; */ extern int fetch_if_missing; -#define HASH_WRITE_OBJECT 1 -#define HASH_FORMAT_CHECK 2 -#define HASH_RENORMALIZE 4 -#define HASH_SILENT 8 +enum { + INDEX_WRITE_OBJECT = (1 << 0), + INDEX_FORMAT_CHECK = (1 << 1), + INDEX_RENORMALIZE = (1 << 2), +}; + int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags); int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags); +struct object_directory; + +/* + * Populate and return the loose object cache array corresponding to the + * given object ID. + */ +struct oidtree *odb_loose_cache(struct object_directory *odb, + const struct object_id *oid); + +/* Empty the loose object cache for the specified object directory. */ +void odb_clear_loose_cache(struct object_directory *odb); + +/* + * Put in `buf` the name of the file in the local object database that + * would be used to store a loose object with the specified oid. + */ +const char *odb_loose_path(struct object_directory *odb, + struct strbuf *buf, + const struct object_id *oid); + /* - * Create the directory containing the named path, using care to be - * somewhat safe against races. Return one of the scld_error values to - * indicate success/failure. On error, set errno to describe the - * problem. + * Return true iff an alternate object database has a loose object + * with the specified name. This function does not respect replace + * references. + */ +int has_loose_object_nonlocal(const struct object_id *); + +int has_loose_object(const struct object_id *); + +void *map_loose_object(struct repository *r, const struct object_id *oid, + unsigned long *size); + +/* + * Iterate over the files in the loose-object parts of the object + * directory "path", triggering the following callbacks: + * + * - loose_object is called for each loose object we find. + * + * - loose_cruft is called for any files that do not appear to be + * loose objects. Note that we only look in the loose object + * directories "objects/[0-9a-f]{2}/", so we will not report + * "objects/foobar" as cruft. + * + * - loose_subdir is called for each top-level hashed subdirectory + * of the object directory (e.g., "$OBJDIR/f0"). It is called + * after the objects in the directory are processed. * - * SCLD_VANISHED indicates that one of the ancestor directories of the - * path existed at one point during the function call and then - * suddenly vanished, probably because another process pruned the - * directory while we were working. To be robust against this kind of - * race, callers might want to try invoking the function again when it - * returns SCLD_VANISHED. + * Any callback that is NULL will be ignored. Callbacks returning non-zero + * will end the iteration. * - * safe_create_leading_directories() temporarily changes path while it - * is working but restores it before returning. - * safe_create_leading_directories_const() doesn't modify path, even - * temporarily. Both these variants adjust the permissions of the - * created directories to honor core.sharedRepository, so they are best - * suited for files inside the git dir. For working tree files, use - * safe_create_leading_directories_no_share() instead, as it ignores - * the core.sharedRepository setting. + * In the "buf" variant, "path" is a strbuf which will also be used as a + * scratch buffer, but restored to its original contents before + * the function returns. */ -enum scld_error { - SCLD_OK = 0, - SCLD_FAILED = -1, - SCLD_PERMS = -2, - SCLD_EXISTS = -3, - SCLD_VANISHED = -4 -}; -enum scld_error safe_create_leading_directories(char *path); -enum scld_error safe_create_leading_directories_const(const char *path); -enum scld_error safe_create_leading_directories_no_share(char *path); +typedef int each_loose_object_fn(const struct object_id *oid, + const char *path, + void *data); +typedef int each_loose_cruft_fn(const char *basename, + const char *path, + void *data); +typedef int each_loose_subdir_fn(unsigned int nr, + const char *path, + void *data); +int for_each_file_in_obj_subdir(unsigned int subdir_nr, + struct strbuf *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); +int for_each_loose_file_in_objdir(const char *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); +int for_each_loose_file_in_objdir_buf(struct strbuf *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); -int mkdir_in_gitdir(const char *path); +/* + * Iterate over all accessible loose objects without respect to + * reachability. By default, this includes both local and alternate objects. + * The order in which objects are visited is unspecified. + * + * Any flags specific to packs are ignored. + */ +int for_each_loose_object(each_loose_object_fn, void *, + enum for_each_object_flags flags); -int git_open_cloexec(const char *name, int flags); -#define git_open(name) git_open_cloexec(name, O_RDONLY) + +/** + * format_object_header() is a thin wrapper around s xsnprintf() that + * writes the initial "<type> <obj-len>" part of the loose object + * header. It returns the size that snprintf() returns + 1. + */ +int format_object_header(char *str, size_t size, enum object_type type, + size_t objsize); /** * unpack_loose_header() initializes the data stream needed to unpack @@ -69,12 +133,7 @@ int git_open_cloexec(const char *name, int flags); * - ULHR_BAD on error * - ULHR_TOO_LONG if the header was too long * - * It will only parse up to MAX_HEADER_LEN bytes unless an optional - * "hdrbuf" argument is non-NULL. This is intended for use with - * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error) - * reporting. The full header will be extracted to "hdrbuf" for use - * with parse_loose_header(), ULHR_TOO_LONG will still be returned - * from this function to indicate that the header was too long. + * It will only parse up to MAX_HEADER_LEN bytes. */ enum unpack_loose_header_result { ULHR_OK, @@ -85,8 +144,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, - unsigned long bufsiz, - struct strbuf *hdrbuf); + unsigned long bufsiz); /** * parse_loose_header() parses the starting "<type> <len>\0" of an @@ -99,6 +157,41 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, struct object_info; int parse_loose_header(const char *hdr, struct object_info *oi); +enum { + /* + * By default, `write_object_file()` does not actually write + * anything into the object store, but only computes the object ID. + * This flag changes that so that the object will be written as a loose + * object and persisted. + */ + WRITE_OBJECT_FILE_PERSIST = (1 << 0), + + /* + * Do not print an error in case something gose wrong. + */ + WRITE_OBJECT_FILE_SILENT = (1 << 1), +}; + +int write_object_file_flags(const void *buf, unsigned long len, + enum object_type type, struct object_id *oid, + struct object_id *compat_oid_in, unsigned flags); +static inline int write_object_file(const void *buf, unsigned long len, + enum object_type type, struct object_id *oid) +{ + return write_object_file_flags(buf, len, type, oid, NULL, 0); +} + +struct input_stream { + const void *(*read)(struct input_stream *, unsigned long *len); + void *data; + int is_finished; +}; + +int stream_loose_object(struct input_stream *in_stream, size_t len, + struct object_id *oid); + +int force_object_loose(const struct object_id *oid, time_t mtime); + /** * With in-core object data in "buf", rehash it to make sure the * object name actually matches "oid" to detect object corruption. @@ -117,6 +210,10 @@ int check_object_signature(struct repository *r, const struct object_id *oid, */ int stream_object_signature(struct repository *r, const struct object_id *oid); +int loose_object_info(struct repository *r, + const struct object_id *oid, + struct object_info *oi, int flags); + enum finalize_object_file_flags { FOF_SKIP_COLLISION_CHECK = 1, }; @@ -125,13 +222,25 @@ int finalize_object_file(const char *tmpfile, const char *filename); int finalize_object_file_flags(const char *tmpfile, const char *filename, enum finalize_object_file_flags flags); +void hash_object_file(const struct git_hash_algo *algo, const void *buf, + unsigned long len, enum object_type type, + struct object_id *oid); + /* Helper to check and "touch" a file */ int check_and_freshen_file(const char *fn, int freshen); -void *read_object_with_reference(struct repository *r, - const struct object_id *oid, - enum object_type required_type, - unsigned long *size, - struct object_id *oid_ret); +/* + * Open the loose object at path, check its hash, and return the contents, + * use the "oi" argument to assert things about the object, or e.g. populate its + * type, and size. If the object is a blob, then "contents" may return NULL, + * to allow streaming of large blobs. + * + * Returns 0 on success, negative on error (details may be written to stderr). + */ +int read_loose_object(const char *path, + const struct object_id *expected_oid, + struct object_id *real_oid, + void **contents, + struct object_info *oi); #endif /* OBJECT_FILE_H */ |