From: Junio C Hamano Date: Mon, 31 Oct 2016 20:15:21 +0000 (-0700) Subject: Merge branch 'ls/git-open-cloexec' X-Git-Tag: v2.11.0-rc0~11 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/906d6906fb580f2002bfdaadab80da6884bab16f?ds=inline;hp=-c Merge branch 'ls/git-open-cloexec' Git generally does not explicitly close file descriptors that were open in the parent process when spawning a child process, but most of the time the child does not want to access them. As Windows does not allow removing or renaming a file that has a file descriptor open, a slow-to-exit child can even break the parent process by holding onto them. Use O_CLOEXEC flag to open files in various codepaths. * ls/git-open-cloexec: read-cache: make sure file handles are not inherited by child processes sha1_file: open window into packfiles with O_CLOEXEC sha1_file: rename git_open_noatime() to git_open() --- 906d6906fb580f2002bfdaadab80da6884bab16f diff --combined cache.h index 1be6526d14,a902ca1f8e..a50a61a197 --- a/cache.h +++ b/cache.h @@@ -409,7 -409,6 +409,7 @@@ static inline enum object_type object_t #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE" #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE" #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX" +#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX" #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" @@@ -434,7 -433,6 +434,7 @@@ #define GIT_GLOB_PATHSPECS_ENVIRONMENT "GIT_GLOB_PATHSPECS" #define GIT_NOGLOB_PATHSPECS_ENVIRONMENT "GIT_NOGLOB_PATHSPECS" #define GIT_ICASE_PATHSPECS_ENVIRONMENT "GIT_ICASE_PATHSPECS" +#define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH" /* * This environment variable is expected to contain a boolean indicating @@@ -477,7 -475,6 +477,7 @@@ extern int get_common_dir_noenv(struct extern int get_common_dir(struct strbuf *sb, const char *gitdir); extern const char *get_git_namespace(void); extern const char *strip_namespace(const char *namespaced_ref); +extern const char *get_super_prefix(void); extern const char *get_git_work_tree(void); /* @@@ -903,8 -900,8 +903,8 @@@ extern char *sha1_pack_index_name(cons * The result will be at least `len` characters long, and will be NUL * terminated. * - * The non-`_r` version returns a static buffer which will be overwritten by - * subsequent calls. + * The non-`_r` version returns a static buffer which remains valid until 4 + * more calls to find_unique_abbrev are made. * * The `_r` variant writes to a buffer supplied by the caller, which must be at * least `GIT_SHA1_HEXSZ + 1` bytes. The return value is the number of bytes @@@ -1125,7 -1122,7 +1125,7 @@@ extern int write_sha1_file(const void * extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int force_object_loose(const unsigned char *sha1, time_t mtime); - extern int git_open_noatime(const char *name); + extern int git_open(const char *name); extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size); extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz); extern int parse_sha1_header(const char *hdr, unsigned long *sizep); @@@ -1157,7 -1154,6 +1157,7 @@@ static inline int has_sha1_file(const u /* Same as the above, except for struct object_id. */ extern int has_object_file(const struct object_id *oid); +extern int has_object_file_with_flags(const struct object_id *oid, int flags); /* * Return true iff an alternate object database has a loose object @@@ -1190,9 -1186,6 +1190,9 @@@ static inline int hex2chr(const char *s #define MINIMUM_ABBREV minimum_abbrev #define DEFAULT_ABBREV default_abbrev +/* used when the code does not know or care what the default abbrev is */ +#define FALLBACK_DEFAULT_ABBREV 7 + struct object_context { unsigned char tree[20]; char path[PATH_MAX]; @@@ -1493,12 -1486,6 +1493,12 @@@ extern void prepare_packed_git(void) extern void reprepare_packed_git(void); extern void install_packed_git(struct packed_git *pack); +/* + * Give a rough count of objects in the repository. This sacrifices accuracy + * for speed. + */ +unsigned long approximate_object_count(void); + extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); diff --combined sha1_file.c index 1e41954a84,09045df1dc..5457314e6a --- a/sha1_file.c +++ b/sha1_file.c @@@ -370,7 -370,7 +370,7 @@@ void read_info_alternates(const char * int fd; path = xstrfmt("%s/info/alternates", relative_base); - fd = git_open_noatime(path); + fd = git_open(path); free(path); if (fd < 0) return; @@@ -663,7 -663,7 +663,7 @@@ static int check_packed_git_idx(const c struct pack_idx_header *hdr; size_t idx_size; uint32_t version, nr, i, *index; - int fd = git_open_noatime(path); + int fd = git_open(path); struct stat st; if (fd < 0) @@@ -1069,7 -1069,7 +1069,7 @@@ static int open_packed_git_1(struct pac while (pack_max_fds <= pack_open_fds && close_one_pack()) ; /* nothing */ - p->pack_fd = git_open_noatime(p->pack_name); + p->pack_fd = git_open(p->pack_name); if (p->pack_fd < 0 || fstat(p->pack_fd, &st)) return -1; pack_open_fds++; @@@ -1410,32 -1410,6 +1410,32 @@@ static void prepare_packed_git_one(cha strbuf_release(&path); } +static int approximate_object_count_valid; + +/* + * Give a fast, rough count of the number of objects in the repository. This + * ignores loose objects completely. If you have a lot of them, then either + * you should repack because your performance will be awful, or they are + * all unreachable objects about to be pruned, in which case they're not really + * interesting as a measure of repo size in the first place. + */ +unsigned long approximate_object_count(void) +{ + static unsigned long count; + if (!approximate_object_count_valid) { + struct packed_git *p; + + prepare_packed_git(); + count = 0; + for (p = packed_git; p; p = p->next) { + if (open_pack_index(p)) + continue; + count += p->num_objects; + } + } + return count; +} + static void *get_next_packed_git(const void *p) { return ((const struct packed_git *)p)->next; @@@ -1507,7 -1481,6 +1507,7 @@@ void prepare_packed_git(void void reprepare_packed_git(void) { + approximate_object_count_valid = 0; prepare_packed_git_run_once = 0; prepare_packed_git(); } @@@ -1586,9 -1559,9 +1586,9 @@@ int check_sha1_signature(const unsigne return hashcmp(sha1, real_sha1) ? -1 : 0; } - int git_open_noatime(const char *name) + int git_open(const char *name) { - static int sha1_file_open_flag = O_NOATIME; + static int sha1_file_open_flag = O_NOATIME | O_CLOEXEC; for (;;) { int fd; @@@ -1598,12 -1571,17 +1598,17 @@@ if (fd >= 0) return fd; - /* Might the failure be due to O_NOATIME? */ - if (errno != ENOENT && sha1_file_open_flag) { - sha1_file_open_flag = 0; + /* Try again w/o O_CLOEXEC: the kernel might not support it */ + if ((sha1_file_open_flag & O_CLOEXEC) && errno == EINVAL) { + sha1_file_open_flag &= ~O_CLOEXEC; continue; } + /* Might the failure be due to O_NOATIME? */ + if (errno != ENOENT && (sha1_file_open_flag & O_NOATIME)) { + sha1_file_open_flag &= ~O_NOATIME; + continue; + } return -1; } } @@@ -1632,7 -1610,7 +1637,7 @@@ static int open_sha1_file(const unsigne struct alternate_object_database *alt; int most_interesting_errno; - fd = git_open_noatime(sha1_file_name(sha1)); + fd = git_open(sha1_file_name(sha1)); if (fd >= 0) return fd; most_interesting_errno = errno; @@@ -1640,7 -1618,7 +1645,7 @@@ prepare_alt_odb(); for (alt = alt_odb_list; alt; alt = alt->next) { const char *path = alt_sha1_path(alt, sha1); - fd = git_open_noatime(path); + fd = git_open(path); if (fd >= 0) return fd; if (most_interesting_errno == ENOENT) @@@ -3362,11 -3340,6 +3367,11 @@@ int has_object_file(const struct object return has_sha1_file(oid->hash); } +int has_object_file_with_flags(const struct object_id *oid, int flags) +{ + return has_sha1_file_with_flags(oid->hash, flags); +} + static void check_tree(const void *buf, size_t size) { struct tree_desc desc;