diff options
-rw-r--r-- | CHANGELOG.md | 18 | ||||
-rw-r--r-- | include/git2/common.h | 1 | ||||
-rw-r--r-- | include/git2/diff.h | 12 | ||||
-rw-r--r-- | include/git2/pack.h | 8 | ||||
-rwxr-xr-x | script/cibuild.sh | 4 | ||||
-rwxr-xr-x | script/install-deps-osx.sh | 2 | ||||
-rw-r--r-- | script/user_model.c | 75 | ||||
-rw-r--r-- | src/apply.c | 7 | ||||
-rw-r--r-- | src/crlf.c | 1 | ||||
-rw-r--r-- | src/global.c | 5 | ||||
-rw-r--r-- | src/index.c | 4 | ||||
-rw-r--r-- | src/mwindow.c | 27 | ||||
-rw-r--r-- | src/mwindow.h | 3 | ||||
-rw-r--r-- | src/odb_pack.c | 3 | ||||
-rw-r--r-- | src/pack-objects.c | 148 | ||||
-rw-r--r-- | src/pack-objects.h | 25 | ||||
-rw-r--r-- | src/patch_generate.c | 4 | ||||
-rw-r--r-- | src/patch_parse.c | 8 | ||||
-rw-r--r-- | src/remote.c | 14 | ||||
-rw-r--r-- | src/repository.c | 8 | ||||
-rw-r--r-- | src/settings.c | 8 | ||||
-rw-r--r-- | src/util.c | 6 | ||||
-rw-r--r-- | tests/core/strtol.c | 8 | ||||
-rw-r--r-- | tests/core/useragent.c | 6 | ||||
-rw-r--r-- | tests/iterator/iterator_helpers.c | 10 | ||||
-rw-r--r-- | tests/iterator/iterator_helpers.h | 4 | ||||
-rw-r--r-- | tests/repo/env.c | 277 | ||||
-rw-r--r-- | tests/repo/open.c | 256 |
28 files changed, 555 insertions, 397 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 44d868e7e..241c7be61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,15 @@ v0.24 + 1 directory matching the starting directory will not prevent git from finding a repository in the starting directory or a parent directory. +* Do not fail when deleting remotes in the presence of broken + global configs which contain branches. + ### API additions +* You can now get the user-agent used by libgit2 using the + `GIT_OPT_GET_USER_AGENT` option with `git_libgit2_opts()`. + It is the counterpart to `GIT_OPT_SET_USER_AGENT`. + * `git_commit_create_buffer()` creates a commit and writes it into a user-provided buffer instead of writing it into the object db. @@ -44,9 +51,18 @@ v0.24 + 1 * `git_blob_create_fromchunks()` has been removed in favour of `git_blob_create_fromstream()`. - ### Breaking API changes +* `git_packbuilder_object_count` and `git_packbuilder_written` now + return a `size_t` instead of a `uint32_t` for more thorough + compatibility with the rest of the library. + +* `git_packbuiler_progress` now provides explicitly sized `uint32_t` + values instead of `unsigned int`. + +* `git_diff_file` now includes an `id_abbrev` field that reflects the + number of nibbles set in the `id` field. + v0.24 ------- diff --git a/include/git2/common.h b/include/git2/common.h index d7428d811..18abe46b3 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -158,6 +158,7 @@ typedef enum { GIT_OPT_SET_USER_AGENT, GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, GIT_OPT_SET_SSL_CIPHERS, + GIT_OPT_GET_USER_AGENT, } git_libgit2_opt_t; /** diff --git a/include/git2/diff.h b/include/git2/diff.h index 005b33965..ac5db711c 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -268,11 +268,6 @@ typedef enum { * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta), * then the oid will be zeroes. * - * The `id_abbrev` represents the known length of the `id` field, when - * converted to a hex string. It is generally `GIT_OID_HEXSZ`, unless this - * delta was created from reading a patch file, in which case it may be - * abbreviated to something reasonable, like 7 characters. - * * `path` is the NUL-terminated path to the entry relative to the working * directory of the repository. * @@ -282,14 +277,19 @@ typedef enum { * * `mode` is, roughly, the stat() `st_mode` value for the item. This will * be restricted to one of the `git_filemode_t` values. + * + * The `id_abbrev` represents the known length of the `id` field, when + * converted to a hex string. It is generally `GIT_OID_HEXSZ`, unless this + * delta was created from reading a patch file, in which case it may be + * abbreviated to something reasonable, like 7 characters. */ typedef struct { git_oid id; - int id_abbrev; const char *path; git_off_t size; uint32_t flags; uint16_t mode; + uint16_t id_abbrev; } git_diff_file; /** diff --git a/include/git2/pack.h b/include/git2/pack.h index 4941998eb..2dfd825e9 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -196,7 +196,7 @@ GIT_EXTERN(int) git_packbuilder_foreach(git_packbuilder *pb, git_packbuilder_for * @param pb the packbuilder * @return the number of objects in the packfile */ -GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb); +GIT_EXTERN(size_t) git_packbuilder_object_count(git_packbuilder *pb); /** * Get the number of objects the packbuilder has already written out @@ -204,13 +204,13 @@ GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb); * @param pb the packbuilder * @return the number of objects which have already been written */ -GIT_EXTERN(uint32_t) git_packbuilder_written(git_packbuilder *pb); +GIT_EXTERN(size_t) git_packbuilder_written(git_packbuilder *pb); /** Packbuilder progress notification function */ typedef int (*git_packbuilder_progress)( int stage, - unsigned int current, - unsigned int total, + uint32_t current, + uint32_t total, void *payload); /** diff --git a/script/cibuild.sh b/script/cibuild.sh index 92e926490..979eb0ce4 100755 --- a/script/cibuild.sh +++ b/script/cibuild.sh @@ -6,6 +6,10 @@ then exit $?; fi +if [ "$TRAVIS_OS_NAME" = "osx" ]; then + export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -) +fi + # Should we ask Travis to cache this file? curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar || exit $? # Run this early so we know it's ready by the time we need it diff --git a/script/install-deps-osx.sh b/script/install-deps-osx.sh index 5510379d4..4b8393b19 100755 --- a/script/install-deps-osx.sh +++ b/script/install-deps-osx.sh @@ -3,4 +3,6 @@ set -x brew update +brew install homebrew/dupes/zlib +brew install curl brew install libssh2 diff --git a/script/user_model.c b/script/user_model.c new file mode 100644 index 000000000..a933d735c --- /dev/null +++ b/script/user_model.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +void *realloc(void *ptr, size_t size); +void *memmove(void *dest, const void *src, size_t n); +size_t strlen(const char *s); + +typedef struct va_list_str *va_list; + +typedef struct git_vector { + void **contents; + size_t length; +} git_vector; + +typedef struct git_buf { + char *ptr; + size_t asize, size; +} git_buf; + +int git_vector_insert(git_vector *v, void *element) +{ + if (!v) + __coverity_panic__(); + + v->contents = realloc(v->contents, ++v->length); + if (!v->contents) + __coverity_panic__(); + v->contents[v->length] = element; + + return 0; +} + +int git_buf_len(const struct git_buf *buf) +{ + return strlen(buf->ptr); +} + +int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) +{ + char ch, *s; + size_t len; + + __coverity_string_null_sink__(format); + __coverity_string_size_sink__(format); + + ch = *format; + ch = *(char *)ap; + + buf->ptr = __coverity_alloc__(len); + __coverity_writeall__(buf->ptr); + buf->size = len; + + return 0; +} + +int git_buf_put(git_buf *buf, const char *data, size_t len) +{ + buf->ptr = __coverity_alloc__(buf->size + len + 1); + memmove(buf->ptr + buf->size, data, len); + buf->size += len; + buf->ptr[buf->size + len] = 0; + return 0; +} + +int git_buf_set(git_buf *buf, const void *data, size_t len) +{ + buf->ptr = __coverity_alloc__(len + 1); + memmove(buf->ptr, data, len); + buf->size = len + 1; + return 0; +} diff --git a/src/apply.c b/src/apply.c index 876860754..40ba647f4 100644 --- a/src/apply.c +++ b/src/apply.c @@ -53,7 +53,10 @@ static int patch_image_init_fromstr( for (start = in; start < in + in_len; start = end) { end = memchr(start, '\n', in_len); - if (end < in + in_len) + if (end == NULL) + end = in + in_len; + + else if (end < in + in_len) end++; line = git_pool_mallocz(&out->pool, 1); @@ -97,7 +100,7 @@ static bool match_hunk( git_diff_line *preimage_line = git_vector_get(&preimage->lines, i); git_diff_line *image_line = git_vector_get(&image->lines, linenum + i); - if (preimage_line->content_len != preimage_line->content_len || + if (preimage_line->content_len != image_line->content_len || memcmp(preimage_line->content, image_line->content, image_line->content_len) != 0) { match = 0; break; diff --git a/src/crlf.c b/src/crlf.c index 5d7510ac7..11895b19f 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -289,6 +289,7 @@ static int crlf_check( ca.eol = check_eol(attr_values[1]); /* eol */ } ca.auto_crlf = GIT_AUTO_CRLF_DEFAULT; + ca.safe_crlf = GIT_SAFE_CRLF_DEFAULT; /* * Use the core Git logic to see if we should perform CRLF for this file diff --git a/src/global.c b/src/global.c index eee0aea57..45b1ab8f6 100644 --- a/src/global.c +++ b/src/global.c @@ -61,8 +61,9 @@ static int init_common(void) (ret = git_sysdir_global_init()) == 0 && (ret = git_filter_global_init()) == 0 && (ret = git_merge_driver_global_init()) == 0 && - (ret = git_transport_ssh_global_init()) == 0) - ret = git_openssl_stream_global_init(); + (ret = git_transport_ssh_global_init()) == 0 && + (ret = git_openssl_stream_global_init()) == 0) + ret = git_mwindow_global_init(); GIT_MEMORY_BARRIER; diff --git a/src/index.c b/src/index.c index 6546ea18a..9908ba64b 100644 --- a/src/index.c +++ b/src/index.c @@ -2160,12 +2160,12 @@ static int read_reuc(git_index *index, const char *buffer, size_t size) if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 || !endptr || endptr == buffer || *endptr || - tmp < 0) { + tmp < 0 || tmp > UINT32_MAX) { index_entry_reuc_free(lost); return index_error_invalid("reading reuc entry stage"); } - lost->mode[i] = tmp; + lost->mode[i] = (uint32_t)tmp; len = (endptr + 1) - buffer; if (size <= len) { diff --git a/src/mwindow.c b/src/mwindow.c index d3e9be78b..8a5b5caee 100644 --- a/src/mwindow.c +++ b/src/mwindow.c @@ -33,25 +33,20 @@ static git_mwindow_ctl mem_ctl; /* Global list of mwindow files, to open packs once across repos */ git_strmap *git__pack_cache = NULL; -/** - * Run under mwindow lock - */ -int git_mwindow_files_init(void) +static void git_mwindow_files_free(void) { - if (git__pack_cache) - return 0; - - git__on_shutdown(git_mwindow_files_free); + git_strmap *tmp = git__pack_cache; - return git_strmap_alloc(&git__pack_cache); + git__pack_cache = NULL; + git_strmap_free(tmp); } -void git_mwindow_files_free(void) +int git_mwindow_global_init(void) { - git_strmap *tmp = git__pack_cache; + assert(!git__pack_cache); - git__pack_cache = NULL; - git_strmap_free(tmp); + git__on_shutdown(git_mwindow_files_free); + return git_strmap_alloc(&git__pack_cache); } int git_mwindow_get_pack(struct git_pack_file **out, const char *path) @@ -69,12 +64,6 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path) return -1; } - if (git_mwindow_files_init() < 0) { - git_mutex_unlock(&git__mwindow_mutex); - git__free(packname); - return -1; - } - pos = git_strmap_lookup_index(git__pack_cache, packname); git__free(packname); diff --git a/src/mwindow.h b/src/mwindow.h index 63418e458..bdde9e0a4 100644 --- a/src/mwindow.h +++ b/src/mwindow.h @@ -43,8 +43,7 @@ int git_mwindow_file_register(git_mwindow_file *mwf); void git_mwindow_file_deregister(git_mwindow_file *mwf); void git_mwindow_close(git_mwindow **w_cursor); -int git_mwindow_files_init(void); -void git_mwindow_files_free(void); +extern int git_mwindow_global_init(void); struct git_pack_file; /* just declaration to avoid cyclical includes */ int git_mwindow_get_pack(struct git_pack_file **out, const char *path); diff --git a/src/odb_pack.c b/src/odb_pack.c index 244e12bc3..005d07264 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -591,9 +591,6 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir) struct pack_backend *backend = NULL; git_buf path = GIT_BUF_INIT; - if (git_mwindow_files_init() < 0) - return -1; - if (pack_backend__alloc(&backend, 8) < 0) return -1; diff --git a/src/pack-objects.c b/src/pack-objects.c index 288aebb20..9f62322f7 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -28,7 +28,7 @@ struct unpacked { git_pobject *object; void *data; struct git_delta_index *index; - int depth; + size_t depth; }; struct tree_walk_context { @@ -99,8 +99,15 @@ static int packbuilder_config(git_packbuilder *pb) #define config_get(KEY,DST,DFLT) do { \ ret = git_config_get_int64(&val, config, KEY); \ - if (!ret) (DST) = val; \ - else if (ret == GIT_ENOTFOUND) { \ + if (!ret) { \ + if (!git__is_sizet(val)) { \ + giterr_set(GITERR_CONFIG, \ + "configuration value '%s' is too large", KEY); \ + ret = -1; \ + goto out; \ + } \ + (DST) = (size_t)val; \ + } else if (ret == GIT_ENOTFOUND) { \ (DST) = (DFLT); \ ret = 0; \ } else if (ret < 0) goto out; } while (0) @@ -187,7 +194,7 @@ static void rehash(git_packbuilder *pb) { git_pobject *po; khiter_t pos; - unsigned int i; + size_t i; int ret; kh_clear(oid, pb->object_ix); @@ -222,7 +229,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, return -1; } - pb->nr_alloc = (uint32_t)newsize; + pb->nr_alloc = newsize; pb->object_list = git__reallocarray(pb->object_list, pb->nr_alloc, sizeof(*po)); @@ -272,7 +279,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, static int get_delta(void **out, git_odb *odb, git_pobject *po) { git_odb_object *src = NULL, *trg = NULL; - unsigned long delta_size; + size_t delta_size; void *delta_buf; int error; @@ -441,8 +448,8 @@ static int write_one( return write_object(pb, po, write_cb, cb_data); } -GIT_INLINE(void) add_to_write_order(git_pobject **wo, unsigned int *endp, - git_pobject *po) +GIT_INLINE(void) add_to_write_order(git_pobject **wo, size_t *endp, + git_pobject *po) { if (po->filled) return; @@ -450,8 +457,8 @@ GIT_INLINE(void) add_to_write_order(git_pobject **wo, unsigned int *endp, po->filled = 1; } -static void add_descendants_to_write_order(git_pobject **wo, unsigned int *endp, - git_pobject *po) +static void add_descendants_to_write_order(git_pobject **wo, size_t *endp, + git_pobject *po) { int add_to_order = 1; while (po) { @@ -492,8 +499,8 @@ static void add_descendants_to_write_order(git_pobject **wo, unsigned int *endp, }; } -static void add_family_to_write_order(git_pobject **wo, unsigned int *endp, - git_pobject *po) +static void add_family_to_write_order(git_pobject **wo, size_t *endp, + git_pobject *po) { git_pobject *root; @@ -524,7 +531,7 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data) static git_pobject **compute_write_order(git_packbuilder *pb) { - unsigned int i, wo_end, last_untagged; + size_t i, wo_end, last_untagged; git_pobject **wo; if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL) @@ -629,13 +636,18 @@ static int write_pack(git_packbuilder *pb, enum write_one_status status; struct git_pack_header ph; git_oid entry_oid; - unsigned int i = 0; + size_t i = 0; int error = 0; write_order = compute_write_order(pb); if (write_order == NULL) return -1; + if (!git__is_uint32(pb->nr_objects)) { + giterr_set(GITERR_INVALID, "too many objects"); + return -1; + } + /* Write pack header */ ph.hdr_signature = htonl(PACK_SIGNATURE); ph.hdr_version = htonl(PACK_VERSION); @@ -711,11 +723,18 @@ static int type_size_sort(const void *_a, const void *_b) return a < b ? -1 : (a > b); /* newest first */ } -static int delta_cacheable(git_packbuilder *pb, unsigned long src_size, - unsigned long trg_size, unsigned long delta_size) +static int delta_cacheable( + git_packbuilder *pb, + size_t src_size, + size_t trg_size, + size_t delta_size) { - if (pb->max_delta_cache_size && - pb->delta_cache_size + delta_size > pb->max_delta_cache_size) + size_t new_size; + + if (git__add_sizet_overflow(&new_size, pb->delta_cache_size, delta_size)) + return 0; + + if (pb->max_delta_cache_size && new_size > pb->max_delta_cache_size) return 0; if (delta_size < pb->cache_max_small_delta_size) @@ -729,15 +748,14 @@ static int delta_cacheable(git_packbuilder *pb, unsigned long src_size, } static int try_delta(git_packbuilder *pb, struct unpacked *trg, - struct unpacked *src, int max_depth, - unsigned long *mem_usage, int *ret) + struct unpacked *src, size_t max_depth, + size_t *mem_usage, int *ret) { git_pobject *trg_object = trg->object; git_pobject *src_object = src->object; git_odb_object *obj; - unsigned long trg_size, src_size, delta_size, - sizediff, max_size, sz; - unsigned int ref_depth; + size_t trg_size, src_size, delta_size, sizediff, max_size, sz; + size_t ref_depth; void *delta_buf; /* Don't bother doing diffs between different types */ @@ -755,7 +773,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, return 0; /* Now some size filtering heuristics. */ - trg_size = (unsigned long)trg_object->size; + trg_size = trg_object->size; if (!trg_object->delta) { max_size = trg_size/2 - 20; ref_depth = 1; @@ -769,7 +787,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, if (max_size == 0) return 0; - src_size = (unsigned long)src_object->size; + src_size = src_object->size; sizediff = src_size < trg_size ? trg_size - src_size : 0; if (sizediff >= max_size) return 0; @@ -781,7 +799,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, if (git_odb_read(&obj, pb->odb, &trg_object->id) < 0) return -1; - sz = (unsigned long)git_odb_object_size(obj); + sz = git_odb_object_size(obj); trg->data = git__malloc(sz); GITERR_CHECK_ALLOC(trg->data); memcpy(trg->data, git_odb_object_data(obj), sz); @@ -803,7 +821,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, !git__is_ulong(obj_sz = git_odb_object_size(obj))) return -1; - sz = (unsigned long)obj_sz; + sz = obj_sz; src->data = git__malloc(sz); GITERR_CHECK_ALLOC(src->data); memcpy(src->data, git_odb_object_data(obj), sz); @@ -841,11 +859,12 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, git_packbuilder__cache_lock(pb); if (trg_object->delta_data) { git__free(trg_object->delta_data); + assert(pb->delta_cache_size >= trg_object->delta_size); pb->delta_cache_size -= trg_object->delta_size; trg_object->delta_data = NULL; } if (delta_cacheable(pb, src_size, trg_size, delta_size)) { - bool overflow = git__add_uint64_overflow( + bool overflow = git__add_sizet_overflow( &pb->delta_cache_size, pb->delta_cache_size, delta_size); git_packbuilder__cache_unlock(pb); @@ -871,13 +890,13 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, return 0; } -static unsigned int check_delta_limit(git_pobject *me, unsigned int n) +static size_t check_delta_limit(git_pobject *me, size_t n) { git_pobject *child = me->delta_child; - unsigned int m = n; + size_t m = n; while (child) { - unsigned int c = check_delta_limit(child, n + 1); + size_t c = check_delta_limit(child, n + 1); if (m < c) m = c; child = child->delta_sibling; @@ -885,9 +904,9 @@ static unsigned int check_delta_limit(git_pobject *me, unsigned int n) return m; } -static unsigned long free_unpacked(struct unpacked *n) +static size_t free_unpacked(struct unpacked *n) { - unsigned long freed_mem = 0; + size_t freed_mem = 0; if (n->index) { freed_mem += git_delta_index_size(n->index); @@ -896,7 +915,7 @@ static unsigned long free_unpacked(struct unpacked *n) n->index = NULL; if (n->data) { - freed_mem += (unsigned long)n->object->size; + freed_mem += n->object->size; git__free(n->data); n->data = NULL; } @@ -905,7 +924,8 @@ static unsigned long free_unpacked(struct unpacked *n) return freed_mem; } -static int report_delta_progress(git_packbuilder *pb, uint32_t count, bool force) +static int report_delta_progress( + git_packbuilder *pb, uint32_t count, bool force) { int ret; @@ -929,15 +949,14 @@ static int report_delta_progress(git_packbuilder *pb, uint32_t count, bool force } static int find_deltas(git_packbuilder *pb, git_pobject **list, - unsigned int *list_size, unsigned int window, - int depth) + size_t *list_size, size_t window, size_t depth) { git_pobject *po; git_buf zbuf = GIT_BUF_INIT; struct unpacked *array; - uint32_t idx = 0, count = 0; - unsigned long mem_usage = 0; - unsigned int i; + size_t idx = 0, count = 0; + size_t mem_usage = 0; + size_t i; int error = -1; array = git__calloc(window, sizeof(struct unpacked)); @@ -945,7 +964,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, for (;;) { struct unpacked *n = array + idx; - int max_depth, j, best_base = -1; + size_t max_depth, j, best_base = SIZE_MAX; git_packbuilder__progress_lock(pb); if (!*list_size) { @@ -966,7 +985,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, while (pb->window_memory_limit && mem_usage > pb->window_memory_limit && count > 1) { - uint32_t tail = (idx + window - count) % window; + size_t tail = (idx + window - count) % window; mem_usage -= free_unpacked(array + tail); count--; } @@ -978,15 +997,18 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, */ max_depth = depth; if (po->delta_child) { - max_depth -= check_delta_limit(po, 0); - if (max_depth <= 0) + size_t delta_limit = check_delta_limit(po, 0); + + if (delta_limit > max_depth) goto next; + + max_depth -= delta_limit; } j = window; while (--j > 0) { int ret; - uint32_t other_idx = idx + j; + size_t other_idx = idx + j; struct unpacked *m; if (other_idx >= window) @@ -1027,7 +1049,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, GITERR_CHECK_ALLOC(po->delta_data); memcpy(po->delta_data, zbuf.ptr, zbuf.size); - po->z_delta_size = (unsigned long)zbuf.size; + po->z_delta_size = zbuf.size; git_buf_clear(&zbuf); git_packbuilder__cache_lock(pb); @@ -1051,10 +1073,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, */ if (po->delta) { struct unpacked swap = array[best_base]; - int dist = (window + idx - best_base) % window; - int dst = best_base; + size_t dist = (window + idx - best_base) % window; + size_t dst = best_base; while (dist--) { - int src = (dst + 1) % window; + size_t src = (dst + 1) % window; array[dst] = array[src]; dst = src; } @@ -1092,13 +1114,13 @@ struct thread_params { git_cond cond; git_mutex mutex; - unsigned int list_size; - unsigned int remaining; + size_t list_size; + size_t remaining; - int window; - int depth; - int working; - int data_ready; + size_t window; + size_t depth; + size_t working; + size_t data_ready; }; static void *threaded_find_deltas(void *arg) @@ -1140,11 +1162,11 @@ static void *threaded_find_deltas(void *arg) } static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, - unsigned int list_size, unsigned int window, - int depth) + size_t list_size, size_t window, size_t depth) { struct thread_params *p; - int i, ret, active_threads = 0; + size_t i; + int ret, active_threads = 0; if (!pb->nr_threads) pb->nr_threads = git_online_cpus(); @@ -1159,7 +1181,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, /* Partition the work among the threads */ for (i = 0; i < pb->nr_threads; ++i) { - unsigned sub_size = list_size / (pb->nr_threads - i); + size_t sub_size = list_size / (pb->nr_threads - i); /* don't use too small segments or no deltas will be found */ if (sub_size < 2*window && i+1 < pb->nr_threads) @@ -1213,7 +1235,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, while (active_threads) { struct thread_params *target = NULL; struct thread_params *victim = NULL; - unsigned sub_size = 0; + size_t sub_size = 0; /* Start by locating a thread that has transitioned its * 'working' flag from 1 -> 0. This indicates that it is @@ -1293,7 +1315,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, static int prepare_pack(git_packbuilder *pb) { git_pobject **delta_list; - unsigned int i, n = 0; + size_t i, n = 0; if (pb->nr_objects == 0 || pb->done) return 0; /* nothing to do */ @@ -1480,12 +1502,12 @@ cleanup: return error; } -uint32_t git_packbuilder_object_count(git_packbuilder *pb) +size_t git_packbuilder_object_count(git_packbuilder *pb) { return pb->nr_objects; } -uint32_t git_packbuilder_written(git_packbuilder *pb) +size_t git_packbuilder_written(git_packbuilder *pb) { return pb->nr_written; } diff --git a/src/pack-objects.h b/src/pack-objects.h index 82dea81f5..5a84f4158 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -42,8 +42,8 @@ typedef struct git_pobject { * me */ void *delta_data; - unsigned long delta_size; - unsigned long z_delta_size; + size_t delta_size; + size_t z_delta_size; int written:1, recursing:1, @@ -65,10 +65,11 @@ struct git_packbuilder { git_zstream zstream; uint32_t nr_objects, - nr_deltified, - nr_alloc, - nr_written, - nr_remaining; + nr_deltified, + nr_written, + nr_remaining; + + size_t nr_alloc; git_pobject *object_list; @@ -85,13 +86,13 @@ struct git_packbuilder { git_cond progress_cond; /* configs */ - uint64_t delta_cache_size; - uint64_t max_delta_cache_size; - uint64_t cache_max_small_delta_size; - uint64_t big_file_threshold; - uint64_t window_memory_limit; + size_t delta_cache_size; + size_t max_delta_cache_size; + size_t cache_max_small_delta_size; + size_t big_file_threshold; + size_t window_memory_limit; - int nr_threads; /* nr of threads to use */ + unsigned int nr_threads; /* nr of threads to use */ git_packbuilder_progress progress_cb; void *progress_cb_payload; diff --git a/src/patch_generate.c b/src/patch_generate.c index 98c14923d..feac4f67a 100644 --- a/src/patch_generate.c +++ b/src/patch_generate.c @@ -284,7 +284,7 @@ static int create_binary( size_t b_datalen) { git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT; - unsigned long delta_data_len; + size_t delta_data_len; int error; /* The git_delta function accepts unsigned long only */ @@ -310,7 +310,7 @@ static int create_binary( if (error == 0) { error = git_zstream_deflatebuf( - &delta, delta_data, (size_t)delta_data_len); + &delta, delta_data, delta_data_len); git__free(delta_data); } else if (error == GIT_EBUFS) { diff --git a/src/patch_parse.c b/src/patch_parse.c index 7f21e3f8e..82d2d3e2e 100644 --- a/src/patch_parse.c +++ b/src/patch_parse.c @@ -192,7 +192,7 @@ static int parse_header_mode(uint16_t *mode, git_patch_parse_ctx *ctx) static int parse_header_oid( git_oid *oid, - int *oid_len, + uint16_t *oid_len, git_patch_parse_ctx *ctx) { size_t len; @@ -202,14 +202,14 @@ static int parse_header_oid( break; } - if (len < GIT_OID_MINPREFIXLEN || + if (len < GIT_OID_MINPREFIXLEN || len > GIT_OID_HEXSZ || git_oid_fromstrn(oid, ctx->line, len) < 0) return parse_err("invalid hex formatted object id at line %d", ctx->line_num); parse_advance_chars(ctx, len); - *oid_len = (int)len; + *oid_len = (uint16_t)len; return 0; } @@ -897,7 +897,7 @@ done: *out_len = (path - path_start); *out = git__strndup(path_start, *out_len); - return (out == NULL) ? -1 : 0; + return (*out == NULL) ? -1 : 0; } static int check_filenames(git_patch_parsed *patch) diff --git a/src/remote.c b/src/remote.c index 5f89c4026..c1d7d59ea 100644 --- a/src/remote.c +++ b/src/remote.c @@ -2162,15 +2162,21 @@ static int remove_branch_config_related_entries( if (git_buf_printf(&buf, "branch.%.*s.merge", (int)branch_len, branch) < 0) break; - if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) - break; + if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) { + if (error != GIT_ENOTFOUND) + break; + giterr_clear(); + } git_buf_clear(&buf); if (git_buf_printf(&buf, "branch.%.*s.remote", (int)branch_len, branch) < 0) break; - if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) - break; + if ((error = git_config_delete_entry(config, git_buf_cstr(&buf))) < 0) { + if (error != GIT_ENOTFOUND) + break; + giterr_clear(); + } } if (error == GIT_ITEROVER) diff --git a/src/repository.c b/src/repository.c index ecc07806e..cf3d18a2d 100644 --- a/src/repository.c +++ b/src/repository.c @@ -264,7 +264,7 @@ cleanup: * the stack could remove directories name limits, but at the cost of doing * repeated malloc/frees inside the loop below, so let's not do it now. */ -static int find_ceiling_dir_offset( +static size_t find_ceiling_dir_offset( const char *path, const char *ceiling_directories) { @@ -278,7 +278,7 @@ static int find_ceiling_dir_offset( min_len = (size_t)(git_path_root(path) + 1); if (ceiling_directories == NULL || min_len == 0) - return (int)min_len; + return min_len; for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) { for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++); @@ -305,7 +305,7 @@ static int find_ceiling_dir_offset( } } - return (int)(max_len <= min_len ? min_len : max_len); + return (max_len <= min_len ? min_len : max_len); } /* @@ -362,7 +362,7 @@ static int find_repo( dev_t initial_device = 0; int min_iterations; bool in_dot_git; - int ceiling_offset; + size_t ceiling_offset = 0; git_buf_free(repo_path); diff --git a/src/settings.c b/src/settings.c index 21430bce9..cb2317f74 100644 --- a/src/settings.c +++ b/src/settings.c @@ -207,6 +207,14 @@ int git_libgit2_opts(int key, ...) #endif break; + case GIT_OPT_GET_USER_AGENT: + { + git_buf *out = va_arg(ap, git_buf *); + git_buf_sanitize(out); + error = git_buf_sets(out, git__user_agent); + } + break; + default: giterr_set(GITERR_INVALID, "invalid option key"); error = -1; diff --git a/src/util.c b/src/util.c index 3090c7437..e9cccea20 100644 --- a/src/util.c +++ b/src/util.c @@ -128,8 +128,8 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha v = c - 'A' + 10; if (v >= base) break; - nn = n*base + v; - if (nn < n) + nn = n * base + (neg ? -v : v); + if ((!neg && nn < n) || (neg && nn > n)) ovfl = 1; n = nn; } @@ -148,7 +148,7 @@ Return: return -1; } - *result = neg ? -n : n; + *result = n; return 0; } diff --git a/tests/core/strtol.c b/tests/core/strtol.c index 8765e042b..0d3b6a5e6 100644 --- a/tests/core/strtol.c +++ b/tests/core/strtol.c @@ -33,5 +33,13 @@ void test_core_strtol__int64(void) cl_assert(i == 2147483657LL); cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10)); cl_assert(i == -2147483657LL); + cl_git_pass(git__strtol64(&i, " 9223372036854775807 ", NULL, 10)); + cl_assert(i == INT64_MAX); + cl_git_pass(git__strtol64(&i, " -9223372036854775808 ", NULL, 10)); + cl_assert(i == INT64_MIN); + cl_git_pass(git__strtol64(&i, " 0x7fffffffffffffff ", NULL, 16)); + cl_assert(i == INT64_MAX); + cl_git_pass(git__strtol64(&i, " -0x8000000000000000 ", NULL, 16)); + cl_assert(i == INT64_MIN); } diff --git a/tests/core/useragent.c b/tests/core/useragent.c index 6d06693a8..5c09223bb 100644 --- a/tests/core/useragent.c +++ b/tests/core/useragent.c @@ -4,8 +4,14 @@ void test_core_useragent__get(void) { const char *custom_name = "super duper git"; + git_buf buf = GIT_BUF_INIT; cl_assert_equal_p(NULL, git_libgit2__user_agent()); cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, custom_name)); cl_assert_equal_s(custom_name, git_libgit2__user_agent()); + + cl_git_pass(git_libgit2_opts(GIT_OPT_GET_USER_AGENT, &buf)); + cl_assert_equal_s(custom_name, buf.ptr); + + git_buf_free(&buf); } diff --git a/tests/iterator/iterator_helpers.c b/tests/iterator/iterator_helpers.c index a3e803299..ae48fcd46 100644 --- a/tests/iterator/iterator_helpers.c +++ b/tests/iterator/iterator_helpers.c @@ -18,18 +18,16 @@ static void assert_at_end(git_iterator *i, bool verbose) void expect_iterator_items( git_iterator *i, - int expected_flat, + size_t expected_flat, const char **expected_flat_paths, - int expected_total, + size_t expected_total, const char **expected_total_paths) { const git_index_entry *entry; - int count, error; + size_t count; int no_trees = !(git_iterator_flags(i) & GIT_ITERATOR_INCLUDE_TREES); bool v = false; - - if (expected_flat < 0) { v = true; expected_flat = -expected_flat; } - if (expected_total < 0) { v = true; expected_total = -expected_total; } + int error; if (v) fprintf(stderr, "== %s ==\n", no_trees ? "notrees" : "trees"); diff --git a/tests/iterator/iterator_helpers.h b/tests/iterator/iterator_helpers.h index 8d0a17014..1884b41a1 100644 --- a/tests/iterator/iterator_helpers.h +++ b/tests/iterator/iterator_helpers.h @@ -1,9 +1,9 @@ extern void expect_iterator_items( git_iterator *i, - int expected_flat, + size_t expected_flat, const char **expected_flat_paths, - int expected_total, + size_t expected_total, const char **expected_total_paths); extern void expect_advance_over( diff --git a/tests/repo/env.c b/tests/repo/env.c new file mode 100644 index 000000000..5a89c0d49 --- /dev/null +++ b/tests/repo/env.c @@ -0,0 +1,277 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "sysdir.h" +#include <ctype.h> + +static void clear_git_env(void) +{ + cl_setenv("GIT_DIR", NULL); + cl_setenv("GIT_CEILING_DIRECTORIES", NULL); + cl_setenv("GIT_INDEX_FILE", NULL); + cl_setenv("GIT_NAMESPACE", NULL); + cl_setenv("GIT_OBJECT_DIRECTORY", NULL); + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); + cl_setenv("GIT_WORK_TREE", NULL); + cl_setenv("GIT_COMMON_DIR", NULL); +} + +void test_repo_env__initialize(void) +{ + clear_git_env(); +} + +void test_repo_env__cleanup(void) +{ + cl_git_sandbox_cleanup(); + + if (git_path_isdir("attr")) + git_futils_rmdir_r("attr", NULL, GIT_RMDIR_REMOVE_FILES); + if (git_path_isdir("testrepo.git")) + git_futils_rmdir_r("testrepo.git", NULL, GIT_RMDIR_REMOVE_FILES); + if (git_path_isdir("peeled.git")) + git_futils_rmdir_r("peeled.git", NULL, GIT_RMDIR_REMOVE_FILES); + + clear_git_env(); +} + +static int GIT_FORMAT_PRINTF(2, 3) cl_setenv_printf(const char *name, const char *fmt, ...) +{ + int ret; + va_list args; + git_buf buf = GIT_BUF_INIT; + + va_start(args, fmt); + cl_git_pass(git_buf_vprintf(&buf, fmt, args)); + va_end(args); + + ret = cl_setenv(name, git_buf_cstr(&buf)); + git_buf_free(&buf); + return ret; +} + +/* Helper functions for test_repo_open__env, passing through the file and line + * from the caller rather than those of the helper. The expression strings + * distinguish between the possible failures within the helper. */ + +static void env_pass_(const char *path, const char *file, int line) +{ + git_repository *repo; + cl_git_pass_(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + cl_git_pass_(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, line); + cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, line); + cl_assert_at_line(!git_repository_is_bare(repo), file, line); + git_repository_free(repo); +} +#define env_pass(path) env_pass_((path), __FILE__, __LINE__) + +#define cl_git_fail_at_line(expr, file, line) clar__assert((expr) < 0, file, line, "Expected function call to fail: " #expr, NULL, 1) + +static void env_fail_(const char *path, const char *file, int line) +{ + git_repository *repo; + cl_git_fail_at_line(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + cl_git_fail_at_line(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); +} +#define env_fail(path) env_fail_((path), __FILE__, __LINE__) + +static void env_cd_( + const char *path, + void (*passfail_)(const char *, const char *, int), + const char *file, int line) +{ + git_buf cwd_buf = GIT_BUF_INIT; + cl_git_pass(git_path_prettify_dir(&cwd_buf, ".", NULL)); + cl_must_pass(p_chdir(path)); + passfail_(NULL, file, line); + cl_must_pass(p_chdir(git_buf_cstr(&cwd_buf))); + git_buf_free(&cwd_buf); +} +#define env_cd_pass(path) env_cd_((path), env_pass_, __FILE__, __LINE__) +#define env_cd_fail(path) env_cd_((path), env_fail_, __FILE__, __LINE__) + +static void env_check_objects_(bool a, bool t, bool p, const char *file, int line) +{ + git_repository *repo; + git_oid oid_a, oid_t, oid_p; + git_object *object; + cl_git_pass(git_oid_fromstr(&oid_a, "45141a79a77842c59a63229403220a4e4be74e3d")); + cl_git_pass(git_oid_fromstr(&oid_t, "1385f264afb75a56a5bec74243be9b367ba4ca08")); + cl_git_pass(git_oid_fromstr(&oid_p, "0df1a5865c8abfc09f1f2182e6a31be550e99f07")); + cl_git_pass_(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + + if (a) { + cl_git_pass_(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); + git_object_free(object); + } else { + cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); + } + + if (t) { + cl_git_pass_(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); + git_object_free(object); + } else { + cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); + } + + if (p) { + cl_git_pass_(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); + git_object_free(object); + } else { + cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); + } + + git_repository_free(repo); +} +#define env_check_objects(a, t, t2) env_check_objects_((a), (t), (t2), __FILE__, __LINE__) + +void test_repo_env__open(void) +{ + git_repository *repo = NULL; + git_buf repo_dir_buf = GIT_BUF_INIT; + const char *repo_dir = NULL; + git_index *index = NULL; + const char *t_obj = "testrepo.git/objects"; + const char *p_obj = "peeled.git/objects"; + + clear_git_env(); + + cl_fixture_sandbox("attr"); + cl_fixture_sandbox("testrepo.git"); + cl_fixture_sandbox("peeled.git"); + cl_git_pass(p_rename("attr/.gitted", "attr/.git")); + + cl_git_pass(git_path_prettify_dir(&repo_dir_buf, "attr", NULL)); + repo_dir = git_buf_cstr(&repo_dir_buf); + + /* GIT_DIR that doesn't exist */ + cl_setenv("GIT_DIR", "does-not-exist"); + env_fail(NULL); + /* Explicit start_path overrides GIT_DIR */ + env_pass("attr"); + env_pass("attr/.git"); + env_pass("attr/sub"); + env_pass("attr/sub/sub"); + + /* GIT_DIR with relative paths */ + cl_setenv("GIT_DIR", "attr/.git"); + env_pass(NULL); + cl_setenv("GIT_DIR", "attr"); + env_fail(NULL); + cl_setenv("GIT_DIR", "attr/sub"); + env_fail(NULL); + cl_setenv("GIT_DIR", "attr/sub/sub"); + env_fail(NULL); + + /* GIT_DIR with absolute paths */ + cl_setenv_printf("GIT_DIR", "%s/.git", repo_dir); + env_pass(NULL); + cl_setenv("GIT_DIR", repo_dir); + env_fail(NULL); + cl_setenv_printf("GIT_DIR", "%s/sub", repo_dir); + env_fail(NULL); + cl_setenv_printf("GIT_DIR", "%s/sub/sub", repo_dir); + env_fail(NULL); + cl_setenv("GIT_DIR", NULL); + + /* Searching from the current directory */ + env_cd_pass("attr"); + env_cd_pass("attr/.git"); + env_cd_pass("attr/sub"); + env_cd_pass("attr/sub/sub"); + + /* A ceiling directory blocks searches from ascending into that + * directory, but doesn't block the start_path itself. */ + cl_setenv("GIT_CEILING_DIRECTORIES", repo_dir); + env_cd_pass("attr"); + env_cd_fail("attr/sub"); + env_cd_fail("attr/sub/sub"); + + cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s/sub", repo_dir); + env_cd_pass("attr"); + env_cd_pass("attr/sub"); + env_cd_fail("attr/sub/sub"); + + /* Multiple ceiling directories */ + cl_setenv_printf("GIT_CEILING_DIRECTORIES", "123%c%s/sub%cabc", + GIT_PATH_LIST_SEPARATOR, repo_dir, GIT_PATH_LIST_SEPARATOR); + env_cd_pass("attr"); + env_cd_pass("attr/sub"); + env_cd_fail("attr/sub/sub"); + + cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s%c%s/sub", + repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir); + env_cd_pass("attr"); + env_cd_fail("attr/sub"); + env_cd_fail("attr/sub/sub"); + + cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s/sub%c%s", + repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir); + env_cd_pass("attr"); + env_cd_fail("attr/sub"); + env_cd_fail("attr/sub/sub"); + + cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s%c%s/sub/sub", + repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir); + env_cd_pass("attr"); + env_cd_fail("attr/sub"); + env_cd_fail("attr/sub/sub"); + + cl_setenv("GIT_CEILING_DIRECTORIES", NULL); + + /* Index files */ + cl_setenv("GIT_INDEX_FILE", cl_fixture("gitgit.index")); + cl_git_pass(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL)); + cl_git_pass(git_repository_index(&index, repo)); + cl_assert_equal_s(git_index_path(index), cl_fixture("gitgit.index")); + cl_assert_equal_i(git_index_entrycount(index), 1437); + git_index_free(index); + git_repository_free(repo); + cl_setenv("GIT_INDEX_FILE", NULL); + + /* Namespaces */ + cl_setenv("GIT_NAMESPACE", "some-namespace"); + cl_git_pass(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL)); + cl_assert_equal_s(git_repository_get_namespace(repo), "some-namespace"); + git_repository_free(repo); + cl_setenv("GIT_NAMESPACE", NULL); + + /* Object directories and alternates */ + env_check_objects(true, false, false); + + cl_setenv("GIT_OBJECT_DIRECTORY", t_obj); + env_check_objects(false, true, false); + cl_setenv("GIT_OBJECT_DIRECTORY", NULL); + + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", t_obj); + env_check_objects(true, true, false); + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); + + cl_setenv("GIT_OBJECT_DIRECTORY", p_obj); + env_check_objects(false, false, true); + cl_setenv("GIT_OBJECT_DIRECTORY", NULL); + + cl_setenv("GIT_OBJECT_DIRECTORY", t_obj); + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", p_obj); + env_check_objects(false, true, true); + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); + cl_setenv("GIT_OBJECT_DIRECTORY", NULL); + + cl_setenv_printf("GIT_ALTERNATE_OBJECT_DIRECTORIES", + "%s%c%s", t_obj, GIT_PATH_LIST_SEPARATOR, p_obj); + env_check_objects(true, true, true); + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); + + cl_setenv_printf("GIT_ALTERNATE_OBJECT_DIRECTORIES", + "%s%c%s", p_obj, GIT_PATH_LIST_SEPARATOR, t_obj); + env_check_objects(true, true, true); + cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); + + cl_fixture_cleanup("peeled.git"); + cl_fixture_cleanup("testrepo.git"); + cl_fixture_cleanup("attr"); + + git_buf_free(&repo_dir_buf); + + clear_git_env(); +} diff --git a/tests/repo/open.c b/tests/repo/open.c index 86353dd25..6114ad2e1 100644 --- a/tests/repo/open.c +++ b/tests/repo/open.c @@ -3,26 +3,6 @@ #include "sysdir.h" #include <ctype.h> -static void clear_git_env(void) -{ - cl_setenv("GIT_DIR", NULL); - cl_setenv("GIT_CEILING_DIRECTORIES", NULL); - cl_setenv("GIT_INDEX_FILE", NULL); - cl_setenv("GIT_NAMESPACE", NULL); - cl_setenv("GIT_OBJECT_DIRECTORY", NULL); - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); - cl_setenv("GIT_WORK_TREE", NULL); - cl_setenv("GIT_COMMON_DIR", NULL); -} - -static git_buf cwd_backup_buf = GIT_BUF_INIT; - -void test_repo_open__initialize(void) -{ - if (!git_buf_is_allocated(&cwd_backup_buf)) - cl_git_pass(git_path_prettify_dir(&cwd_backup_buf, ".", NULL)); - clear_git_env(); -} void test_repo_open__cleanup(void) { @@ -30,15 +10,6 @@ void test_repo_open__cleanup(void) if (git_path_isdir("alternate")) git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES); - if (git_path_isdir("attr")) - git_futils_rmdir_r("attr", NULL, GIT_RMDIR_REMOVE_FILES); - if (git_path_isdir("testrepo.git")) - git_futils_rmdir_r("testrepo.git", NULL, GIT_RMDIR_REMOVE_FILES); - if (git_path_isdir("peeled.git")) - git_futils_rmdir_r("peeled.git", NULL, GIT_RMDIR_REMOVE_FILES); - - cl_must_pass(p_chdir(git_buf_cstr(&cwd_backup_buf))); - clear_git_env(); } void test_repo_open__bare_empty_repo(void) @@ -432,230 +403,3 @@ void test_repo_open__force_bare(void) git_repository_free(barerepo); } -static int GIT_FORMAT_PRINTF(2, 3) cl_setenv_printf(const char *name, const char *fmt, ...) -{ - int ret; - va_list args; - git_buf buf = GIT_BUF_INIT; - - va_start(args, fmt); - cl_git_pass(git_buf_vprintf(&buf, fmt, args)); - va_end(args); - - ret = cl_setenv(name, git_buf_cstr(&buf)); - git_buf_free(&buf); - return ret; -} - -/* Helper functions for test_repo_open__env, passing through the file and line - * from the caller rather than those of the helper. The expression strings - * distinguish between the possible failures within the helper. */ - -static void env_pass_(const char *path, const char *file, int line) -{ - git_repository *repo; - cl_git_pass_(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); - cl_git_pass_(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); - cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, line); - cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, line); - cl_assert_at_line(!git_repository_is_bare(repo), file, line); - git_repository_free(repo); -} -#define env_pass(path) env_pass_((path), __FILE__, __LINE__) - -#define cl_git_fail_at_line(expr, file, line) clar__assert((expr) < 0, file, line, "Expected function call to fail: " #expr, NULL, 1) - -static void env_fail_(const char *path, const char *file, int line) -{ - git_repository *repo; - cl_git_fail_at_line(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); - cl_git_fail_at_line(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); -} -#define env_fail(path) env_fail_((path), __FILE__, __LINE__) - -static void env_cd_( - const char *path, - void (*passfail_)(const char *, const char *, int), - const char *file, int line) -{ - git_buf cwd_buf = GIT_BUF_INIT; - cl_git_pass(git_path_prettify_dir(&cwd_buf, ".", NULL)); - cl_must_pass(p_chdir(path)); - passfail_(NULL, file, line); - cl_must_pass(p_chdir(git_buf_cstr(&cwd_buf))); -} -#define env_cd_pass(path) env_cd_((path), env_pass_, __FILE__, __LINE__) -#define env_cd_fail(path) env_cd_((path), env_fail_, __FILE__, __LINE__) - -static void env_check_objects_(bool a, bool t, bool p, const char *file, int line) -{ - git_repository *repo; - git_oid oid_a, oid_t, oid_p; - git_object *object; - cl_git_pass(git_oid_fromstr(&oid_a, "45141a79a77842c59a63229403220a4e4be74e3d")); - cl_git_pass(git_oid_fromstr(&oid_t, "1385f264afb75a56a5bec74243be9b367ba4ca08")); - cl_git_pass(git_oid_fromstr(&oid_p, "0df1a5865c8abfc09f1f2182e6a31be550e99f07")); - cl_git_pass_(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); - if (a) { - cl_git_pass_(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); - git_object_free(object); - } else - cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); - if (t) { - cl_git_pass_(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); - git_object_free(object); - } else - cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); - if (p) { - cl_git_pass_(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); - git_object_free(object); - } else - cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); - git_repository_free(repo); -} -#define env_check_objects(a, t, t2) env_check_objects_((a), (t), (t2), __FILE__, __LINE__) - -void test_repo_open__env(void) -{ - git_repository *repo = NULL; - git_buf repo_dir_buf = GIT_BUF_INIT; - const char *repo_dir = NULL; - git_index *index = NULL; - const char *t_obj = "testrepo.git/objects"; - const char *p_obj = "peeled.git/objects"; - - cl_fixture_sandbox("attr"); - cl_fixture_sandbox("testrepo.git"); - cl_fixture_sandbox("peeled.git"); - cl_git_pass(p_rename("attr/.gitted", "attr/.git")); - - cl_git_pass(git_path_prettify_dir(&repo_dir_buf, "attr", NULL)); - repo_dir = git_buf_cstr(&repo_dir_buf); - - /* GIT_DIR that doesn't exist */ - cl_setenv("GIT_DIR", "does-not-exist"); - env_fail(NULL); - /* Explicit start_path overrides GIT_DIR */ - env_pass("attr"); - env_pass("attr/.git"); - env_pass("attr/sub"); - env_pass("attr/sub/sub"); - - /* GIT_DIR with relative paths */ - cl_setenv("GIT_DIR", "attr/.git"); - env_pass(NULL); - cl_setenv("GIT_DIR", "attr"); - env_fail(NULL); - cl_setenv("GIT_DIR", "attr/sub"); - env_fail(NULL); - cl_setenv("GIT_DIR", "attr/sub/sub"); - env_fail(NULL); - - /* GIT_DIR with absolute paths */ - cl_setenv_printf("GIT_DIR", "%s/.git", repo_dir); - env_pass(NULL); - cl_setenv("GIT_DIR", repo_dir); - env_fail(NULL); - cl_setenv_printf("GIT_DIR", "%s/sub", repo_dir); - env_fail(NULL); - cl_setenv_printf("GIT_DIR", "%s/sub/sub", repo_dir); - env_fail(NULL); - cl_setenv("GIT_DIR", NULL); - - /* Searching from the current directory */ - env_cd_pass("attr"); - env_cd_pass("attr/.git"); - env_cd_pass("attr/sub"); - env_cd_pass("attr/sub/sub"); - - /* A ceiling directory blocks searches from ascending into that - * directory, but doesn't block the start_path itself. */ - cl_setenv("GIT_CEILING_DIRECTORIES", repo_dir); - env_cd_pass("attr"); - env_cd_fail("attr/sub"); - env_cd_fail("attr/sub/sub"); - - cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s/sub", repo_dir); - env_cd_pass("attr"); - env_cd_pass("attr/sub"); - env_cd_fail("attr/sub/sub"); - - /* Multiple ceiling directories */ - cl_setenv_printf("GIT_CEILING_DIRECTORIES", "123%c%s/sub%cabc", - GIT_PATH_LIST_SEPARATOR, repo_dir, GIT_PATH_LIST_SEPARATOR); - env_cd_pass("attr"); - env_cd_pass("attr/sub"); - env_cd_fail("attr/sub/sub"); - - cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s%c%s/sub", - repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir); - env_cd_pass("attr"); - env_cd_fail("attr/sub"); - env_cd_fail("attr/sub/sub"); - - cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s/sub%c%s", - repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir); - env_cd_pass("attr"); - env_cd_fail("attr/sub"); - env_cd_fail("attr/sub/sub"); - - cl_setenv_printf("GIT_CEILING_DIRECTORIES", "%s%c%s/sub/sub", - repo_dir, GIT_PATH_LIST_SEPARATOR, repo_dir); - env_cd_pass("attr"); - env_cd_fail("attr/sub"); - env_cd_fail("attr/sub/sub"); - - cl_setenv("GIT_CEILING_DIRECTORIES", NULL); - - /* Index files */ - cl_setenv("GIT_INDEX_FILE", cl_fixture("gitgit.index")); - cl_git_pass(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL)); - cl_git_pass(git_repository_index(&index, repo)); - cl_assert_equal_s(git_index_path(index), cl_fixture("gitgit.index")); - cl_assert_equal_i(git_index_entrycount(index), 1437); - git_index_free(index); - git_repository_free(repo); - cl_setenv("GIT_INDEX_FILE", NULL); - - /* Namespaces */ - cl_setenv("GIT_NAMESPACE", "some-namespace"); - cl_git_pass(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL)); - cl_assert_equal_s(git_repository_get_namespace(repo), "some-namespace"); - git_repository_free(repo); - cl_setenv("GIT_NAMESPACE", NULL); - - /* Object directories and alternates */ - env_check_objects(true, false, false); - - cl_setenv("GIT_OBJECT_DIRECTORY", t_obj); - env_check_objects(false, true, false); - cl_setenv("GIT_OBJECT_DIRECTORY", NULL); - - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", t_obj); - env_check_objects(true, true, false); - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); - - cl_setenv("GIT_OBJECT_DIRECTORY", p_obj); - env_check_objects(false, false, true); - cl_setenv("GIT_OBJECT_DIRECTORY", NULL); - - cl_setenv("GIT_OBJECT_DIRECTORY", t_obj); - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", p_obj); - env_check_objects(false, true, true); - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); - cl_setenv("GIT_OBJECT_DIRECTORY", NULL); - - cl_setenv_printf("GIT_ALTERNATE_OBJECT_DIRECTORIES", - "%s%c%s", t_obj, GIT_PATH_LIST_SEPARATOR, p_obj); - env_check_objects(true, true, true); - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); - - cl_setenv_printf("GIT_ALTERNATE_OBJECT_DIRECTORIES", - "%s%c%s", p_obj, GIT_PATH_LIST_SEPARATOR, t_obj); - env_check_objects(true, true, true); - cl_setenv("GIT_ALTERNATE_OBJECT_DIRECTORIES", NULL); - - cl_fixture_cleanup("peeled.git"); - cl_fixture_cleanup("testrepo.git"); - cl_fixture_cleanup("attr"); -} |