diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2015-03-24 16:47:26 +0100 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2015-03-24 16:47:26 +0100 |
commit | 928b4cad520fa87dd192d6363182145a91fcedea (patch) | |
tree | 33763aa2c58761694ced3947b54ab62b69c5321c | |
parent | 79010d09df45ed8cbe1b64fb12786db2ba98f7cd (diff) | |
parent | 1f726d05d382e7f797e9a77dfec8f4383f1000c1 (diff) | |
download | libgit2-928b4cad520fa87dd192d6363182145a91fcedea.tar.gz |
Merge pull request #3005 from libgit2/cmn/maint-update
Backports for the maint branch
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | include/git2/repository.h | 4 | ||||
-rw-r--r-- | include/git2/sys/repository.h | 5 | ||||
-rw-r--r-- | src/branch.c | 7 | ||||
-rw-r--r-- | src/buf_text.c | 5 | ||||
-rw-r--r-- | src/checkout.c | 1 | ||||
-rw-r--r-- | src/config_file.c | 1 | ||||
-rw-r--r-- | src/diff_patch.c | 3 | ||||
-rw-r--r-- | src/fileops.c | 29 | ||||
-rw-r--r-- | src/index.c | 3 | ||||
-rw-r--r-- | src/indexer.c | 1 | ||||
-rw-r--r-- | src/openssl_stream.c | 3 | ||||
-rw-r--r-- | src/pack.c | 11 | ||||
-rw-r--r-- | src/rebase.c | 4 | ||||
-rw-r--r-- | src/refdb_fs.c | 9 | ||||
-rw-r--r-- | src/remote.c | 6 | ||||
-rw-r--r-- | src/repository.c | 2 | ||||
-rw-r--r-- | src/stream.h | 5 | ||||
-rw-r--r-- | src/transports/git.c | 1 | ||||
-rw-r--r-- | src/transports/http.c | 8 | ||||
-rw-r--r-- | src/win32/posix_w32.c | 8 | ||||
-rw-r--r-- | tests/checkout/icase.c | 2 | ||||
-rw-r--r-- | tests/core/buffer.c | 2 | ||||
-rw-r--r-- | tests/core/stat.c | 17 | ||||
-rw-r--r-- | tests/online/fetch.c | 6 | ||||
-rw-r--r-- | tests/refs/branches/create.c | 104 | ||||
-rw-r--r-- | tests/repo/init.c | 26 |
27 files changed, 243 insertions, 36 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b4d42e060..77a591f8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,6 @@ OPTION( VALGRIND "Configure build for valgrind" OFF ) IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") SET( USE_ICONV ON ) - ADD_DEFINITIONS(-DGIT_COMMON_CRYPTO) ENDIF() IF(MSVC) @@ -172,6 +171,8 @@ ENDIF() IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") ADD_DEFINITIONS(-DWIN32_SHA1) FILE(GLOB SRC_SHA1 src/hash/hash_win32.c) +ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + ADD_DEFINITIONS(-DGIT_COMMON_CRYPTO) ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") ADD_DEFINITIONS(-DOPENSSL_SHA1) IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") @@ -217,7 +218,8 @@ IF (USE_SSH) ENDIF() IF (LIBSSH2_FOUND) ADD_DEFINITIONS(-DGIT_SSH) - INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIRS}) + LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS}) SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} libssh2") SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES}) ENDIF() diff --git a/include/git2/repository.h b/include/git2/repository.h index 124aa67e6..2fb381316 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -342,8 +342,8 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo); /** * Check if a repository is empty * - * An empty repository has just been initialized and contains - * no references. + * An empty repository has just been initialized and contains no references + * apart from HEAD, which must be pointing to the unborn master branch. * * @param repo Repo to test * @return 1 if the repository is empty, 0 if it isn't, error code diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h index dd7b22e06..800396c86 100644 --- a/include/git2/sys/repository.h +++ b/include/git2/sys/repository.h @@ -7,6 +7,9 @@ #ifndef INCLUDE_sys_git_repository_h__ #define INCLUDE_sys_git_repository_h__ +#include "git2/common.h" +#include "git2/types.h" + /** * @file git2/sys/repository.h * @brief Git repository custom implementation routines @@ -53,7 +56,7 @@ GIT_EXTERN(void) git_repository__cleanup(git_repository *repo); * * @param repo A repository object * @param recurse_submodules Should submodules be updated recursively - * @returrn 0 on success, < 0 on error + * @return 0 on success, < 0 on error */ GIT_EXTERN(int) git_repository_reinit_filesystem( git_repository *repo, diff --git a/src/branch.c b/src/branch.c index b4e4b0564..b39d74749 100644 --- a/src/branch.c +++ b/src/branch.c @@ -138,8 +138,13 @@ int git_branch_delete(git_reference *branch) if (git_reference_delete(branch) < 0) goto on_error; - if (git_reflog_delete(git_reference_owner(branch), git_reference_name(branch)) < 0) + if ((error = git_reflog_delete(git_reference_owner(branch), git_reference_name(branch))) < 0) { + if (error == GIT_ENOTFOUND) { + giterr_clear(); + error = 0; + } goto on_error; + } error = 0; diff --git a/src/buf_text.c b/src/buf_text.c index cead599f4..cb3661edb 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -191,7 +191,10 @@ bool git_buf_text_is_binary(const git_buf *buf) while (scan < end) { unsigned char c = *scan++; - if (c > 0x1F && c < 0x7F) + /* Printable characters are those above SPACE (0x1F) excluding DEL, + * and including BS, ESC and FF. + */ + if ((c > 0x1F && c != 127) || c == '\b' || c == '\033' || c == '\014') printable++; else if (c == '\0') return true; diff --git a/src/checkout.c b/src/checkout.c index 7b683bbda..6357579cc 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2212,6 +2212,7 @@ static void checkout_data_clear(checkout_data *data) git__free(data->pfx); data->pfx = NULL; + git_buf_free(&data->last_mkdir); git_buf_free(&data->path); git_buf_free(&data->tmp); diff --git a/src/config_file.c b/src/config_file.c index 4f041e7e3..268cced09 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1284,6 +1284,7 @@ static int config_parse(git_strmap *values, diskfile_backend *cfg_file, struct r if (result == 0) { result = config_parse(values, cfg_file, r, level, depth+1); r = git_array_get(cfg_file->readers, index); + reader = git_array_get(cfg_file->readers, reader_idx); } else if (result == GIT_ENOTFOUND) { giterr_clear(); diff --git a/src/diff_patch.c b/src/diff_patch.c index 317dbeabb..7cdf6f39b 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -822,7 +822,8 @@ int git_patch__invoke_callbacks( for (i = 0; !error && i < git_array_size(patch->hunks); ++i) { diff_patch_hunk *h = git_array_get(patch->hunks, i); - error = hunk_cb(patch->delta, &h->hunk, payload); + if (hunk_cb) + error = hunk_cb(patch->delta, &h->hunk, payload); if (!line_cb) continue; diff --git a/src/fileops.c b/src/fileops.c index 59882a968..4b49fa85c 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -330,7 +330,7 @@ int git_futils_mkdir_withperf( { int error = -1; git_buf make_path = GIT_BUF_INIT; - ssize_t root = 0, min_root_len; + ssize_t root = 0, min_root_len, root_len; char lastch = '/', *tail; struct stat st; @@ -343,22 +343,29 @@ int git_futils_mkdir_withperf( goto done; } - /* remove trailing slashes on path */ - while (make_path.ptr[make_path.size - 1] == '/') { - make_path.size--; - make_path.ptr[make_path.size] = '\0'; - } + /* Trim trailing slashes (except the root) */ + if ((root_len = git_path_root(make_path.ptr)) < 0) + root_len = 0; + else + root_len++; + + while (make_path.size > (size_t)root_len && + make_path.ptr[make_path.size - 1] == '/') + make_path.ptr[--make_path.size] = '\0'; /* if we are not supposed to made the last element, truncate it */ if ((flags & GIT_MKDIR_SKIP_LAST2) != 0) { - git_buf_rtruncate_at_char(&make_path, '/'); + git_path_dirname_r(&make_path, make_path.ptr); flags |= GIT_MKDIR_SKIP_LAST; } - if ((flags & GIT_MKDIR_SKIP_LAST) != 0) - git_buf_rtruncate_at_char(&make_path, '/'); + if ((flags & GIT_MKDIR_SKIP_LAST) != 0) { + git_path_dirname_r(&make_path, make_path.ptr); + } - /* if nothing left after truncation, then we're done! */ - if (!make_path.size) { + /* We were either given the root path (or trimmed it to + * the root), we don't have anything to do. + */ + if (make_path.size <= (size_t)root_len) { error = 0; goto done; } diff --git a/src/index.c b/src/index.c index 079b0cb65..cbace3606 100644 --- a/src/index.c +++ b/src/index.c @@ -292,6 +292,9 @@ static void index_entry_reuc_free(git_index_reuc_entry *reuc) static void index_entry_free(git_index_entry *entry) { + if (!entry) + return; + memset(&entry->id, 0, sizeof(entry->id)); git__free(entry); } diff --git a/src/indexer.c b/src/indexer.c index 92f85c167..f328025fd 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -289,6 +289,7 @@ static int store_object(git_indexer *idx) k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error); if (!error) { git__free(pentry); + giterr_set(GITERR_INDEXER, "cannot handle duplicate objects in pack"); goto on_error; } diff --git a/src/openssl_stream.c b/src/openssl_stream.c index 108ccfef2..c02df0b7a 100644 --- a/src/openssl_stream.c +++ b/src/openssl_stream.c @@ -8,6 +8,9 @@ #ifdef GIT_SSL #include <ctype.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> #include "global.h" #include "posix.h" diff --git a/src/pack.c b/src/pack.c index 47ce854c4..6891a7d03 100644 --- a/src/pack.c +++ b/src/pack.c @@ -56,6 +56,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source) if (!e) return NULL; + git_atomic_inc(&e->refcount); memcpy(&e->raw, source, sizeof(git_rawobj)); return e; @@ -145,7 +146,11 @@ static void free_lowest_entry(git_pack_cache *cache) } } -static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset) +static int cache_add( + git_pack_cache_entry **cached_out, + git_pack_cache *cache, + git_rawobj *base, + git_off_t offset) { git_pack_cache_entry *entry; int error, exists = 0; @@ -171,6 +176,8 @@ static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset) assert(error != 0); kh_value(cache->entries, k) = entry; cache->memory_used += entry->raw.len; + + *cached_out = entry; } git_mutex_unlock(&cache->lock); /* Somebody beat us to adding it into the cache */ @@ -699,7 +706,7 @@ int git_packfile_unpack( * long as it's not already the cached one. */ if (!cached) - free_base = !!cache_add(&p->bases, obj, elem->base_key); + free_base = !!cache_add(&cached, &p->bases, obj, elem->base_key); elem = &stack[elem_pos - 1]; curpos = elem->offset; diff --git a/src/rebase.c b/src/rebase.c index ceb74d39f..2e805929e 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -634,7 +634,7 @@ int git_rebase_init( *out = NULL; - GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options"); + GITERR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options"); if (!onto) onto = upstream; @@ -1058,6 +1058,8 @@ int git_rebase_finish( assert(rebase); + GITERR_CHECK_VERSION(given_opts, GIT_REBASE_OPTIONS_VERSION, "git_rebase_options"); + if ((error = rebase_normalize_opts(rebase->repo, &opts, given_opts)) < 0) goto done; diff --git a/src/refdb_fs.c b/src/refdb_fs.c index fc41a95d7..5cd2112fc 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -1771,6 +1771,15 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co goto cleanup; } + /* If the new branch matches part of the namespace of a previously deleted branch, + * there maybe an obsolete/unused directory (or directory hierarchy) in the way. + */ + if (git_path_isdir(git_buf_cstr(&path)) && + (git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0)) { + error = -1; + goto cleanup; + } + error = git_futils_writebuffer(&buf, git_buf_cstr(&path), O_WRONLY|O_CREAT|O_APPEND, GIT_REFLOG_FILE_MODE); cleanup: diff --git a/src/remote.c b/src/remote.c index 5ba7735ae..af5ebdfa6 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1459,7 +1459,7 @@ int git_remote_update_tips( const char *reflog_message) { git_refspec *spec, tagspec; - git_vector refs; + git_vector refs = GIT_VECTOR_INIT; int error; size_t i; @@ -2330,6 +2330,10 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi (error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0) goto cleanup; + free_refspecs(&remote->active_refspecs); + if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0) + goto cleanup; + if (remote->push) { git_push_free(remote->push); remote->push = NULL; diff --git a/src/repository.c b/src/repository.c index 5d5b3e5ea..fe2a2a677 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1724,7 +1724,7 @@ int git_repository_set_bare(git_repository *repo) if ((error = git_repository_config__weakptr(&config, repo)) < 0) return error; - if ((error = git_config_set_bool(config, "core.bare", false)) < 0) + if ((error = git_config_set_bool(config, "core.bare", true)) < 0) return error; if ((error = git_config__update_entry(config, "core.worktree", NULL, true, true)) < 0) diff --git a/src/stream.h b/src/stream.h index 3a7ef9514..d810e704d 100644 --- a/src/stream.h +++ b/src/stream.h @@ -15,6 +15,11 @@ GIT_INLINE(int) git_stream_connect(git_stream *st) return st->connect(st); } +GIT_INLINE(int) git_stream_is_encrypted(git_stream *st) +{ + return st->encrypted; +} + GIT_INLINE(int) git_stream_certificate(git_cert **out, git_stream *st) { if (!st->encrypted) { diff --git a/src/transports/git.c b/src/transports/git.c index 6f25736b1..8ab809117 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -136,6 +136,7 @@ static void git_proto_stream_free(git_smart_subtransport_stream *stream) t->current_stream = NULL; + git_stream_close(s->io); git_stream_free(s->io); git__free(s->url); git__free(s); diff --git a/src/transports/http.c b/src/transports/http.c index 807e08044..0cd33002f 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -350,6 +350,11 @@ static int on_headers_complete(http_parser *parser) } else { assert(t->cred); + if (!(t->cred->credtype & allowed_auth_types)) { + giterr_set(GITERR_NET, "credentials callback returned an invalid cred type"); + return t->parse_error = PARSE_ERROR_GENERIC; + } + /* Successfully acquired a credential. */ t->parse_error = PARSE_ERROR_REPLAY; return 0; @@ -553,7 +558,8 @@ static int http_connect(http_subtransport *t) error = git_stream_connect(t->io); #ifdef GIT_SSL - if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) { + if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL && + git_stream_is_encrypted(t->io)) { git_cert *cert; int is_valid; diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index e446ccab0..346f537e4 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -448,12 +448,8 @@ int p_stat(const char* path, struct stat* buf) git_win32_path path_w; int len; - if ((len = git_win32_path_from_utf8(path_w, path)) < 0) - return -1; - - git_win32__path_trim_end(path_w, len); - - if (lstat_w(path_w, buf, false) < 0) + if ((len = git_win32_path_from_utf8(path_w, path)) < 0 || + lstat_w(path_w, buf, false) < 0) return -1; /* The item is a symbolic link or mount point. No need to iterate diff --git a/tests/checkout/icase.c b/tests/checkout/icase.c index 3a6ce2078..211738070 100644 --- a/tests/checkout/icase.c +++ b/tests/checkout/icase.c @@ -4,7 +4,7 @@ #include "path.h" #ifdef GIT_WIN32 -# include <Windows.h> +# include <windows.h> #endif static git_repository *repo; diff --git a/tests/core/buffer.c b/tests/core/buffer.c index 87dec4607..d28aa218f 100644 --- a/tests/core/buffer.c +++ b/tests/core/buffer.c @@ -830,7 +830,7 @@ void test_core_buffer__classify_with_utf8(void) cl_assert(!git_buf_text_contains_nul(&b)); b.ptr = data1; b.size = b.asize = data1len; - cl_assert(git_buf_text_is_binary(&b)); + cl_assert(!git_buf_text_is_binary(&b)); cl_assert(!git_buf_text_contains_nul(&b)); b.ptr = data2; b.size = b.asize = data2len; diff --git a/tests/core/stat.c b/tests/core/stat.c index 2e4abfb79..bd9b990e3 100644 --- a/tests/core/stat.c +++ b/tests/core/stat.c @@ -95,3 +95,20 @@ void test_core_stat__0(void) cl_assert_error(ENOTDIR); } +void test_core_stat__root(void) +{ + const char *sandbox = clar_sandbox_path(); + git_buf root = GIT_BUF_INIT; + int root_len; + struct stat st; + + root_len = git_path_root(sandbox); + cl_assert(root_len >= 0); + + git_buf_set(&root, sandbox, root_len+1); + + cl_must_pass(p_stat(root.ptr, &st)); + cl_assert(S_ISDIR(st.st_mode)); + + git_buf_free(&root); +} diff --git a/tests/online/fetch.c b/tests/online/fetch.c index 848b87410..484f4b57d 100644 --- a/tests/online/fetch.c +++ b/tests/online/fetch.c @@ -58,17 +58,17 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) void test_online_fetch__default_git(void) { - do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 5); + do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } void test_online_fetch__default_http(void) { - do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 5); + do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } void test_online_fetch__default_https(void) { - do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 5); + do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } void test_online_fetch__no_tags_git(void) diff --git a/tests/refs/branches/create.c b/tests/refs/branches/create.c index 3a4f33b6e..af9963bde 100644 --- a/tests/refs/branches/create.c +++ b/tests/refs/branches/create.c @@ -196,3 +196,107 @@ void test_refs_branches_create__can_create_branch_with_unicode(void) branch = NULL; } } + +/** + * Verify that we can create a branch with a name that matches the + * namespace of a previously delete branch. + * + * git branch level_one/level_two + * git branch -D level_one/level_two + * git branch level_one + * + * We expect the delete to have deleted the files: + * ".git/refs/heads/level_one/level_two" + * ".git/logs/refs/heads/level_one/level_two" + * It may or may not have deleted the (now empty) + * containing directories. To match git.git behavior, + * the second create needs to implicilty delete the + * directories and create the new files. + * "refs/heads/level_one" + * "logs/refs/heads/level_one" + * + * We should not fail to create the branch or its + * reflog because of an obsolete namespace container + * directory. + */ +void test_refs_branches_create__name_vs_namespace(void) +{ + const char * name; + struct item { + const char *first; + const char *second; + }; + static const struct item item[] = { + { "level_one/level_two", "level_one" }, + { "a/b/c/d/e", "a/b/c/d" }, + { "ss/tt/uu/vv/ww", "ss" }, + /* And one test case that is deeper. */ + { "xx1/xx2/xx3/xx4", "xx1/xx2/xx3/xx4/xx5/xx6" }, + { NULL, NULL }, + }; + const struct item *p; + + retrieve_known_commit(&target, repo); + + for (p=item; p->first; p++) { + cl_git_pass(git_branch_create(&branch, repo, p->first, target, 0, NULL, NULL)); + cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); + cl_git_pass(git_branch_name(&name, branch)); + cl_assert_equal_s(name, p->first); + + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); + branch = NULL; + + cl_git_pass(git_branch_create(&branch, repo, p->second, target, 0, NULL, NULL)); + git_reference_free(branch); + branch = NULL; + } +} + +/** + * We still need to fail if part of the namespace is + * still in use. + */ +void test_refs_branches_create__name_vs_namespace_fail(void) +{ + const char * name; + struct item { + const char *first; + const char *first_alternate; + const char *second; + }; + static const struct item item[] = { + { "level_one/level_two", "level_one/alternate", "level_one" }, + { "a/b/c/d/e", "a/b/c/d/alternate", "a/b/c/d" }, + { "ss/tt/uu/vv/ww", "ss/alternate", "ss" }, + { NULL, NULL, NULL }, + }; + const struct item *p; + + retrieve_known_commit(&target, repo); + + for (p=item; p->first; p++) { + cl_git_pass(git_branch_create(&branch, repo, p->first, target, 0, NULL, NULL)); + cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); + cl_git_pass(git_branch_name(&name, branch)); + cl_assert_equal_s(name, p->first); + + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); + branch = NULL; + + cl_git_pass(git_branch_create(&branch, repo, p->first_alternate, target, 0, NULL, NULL)); + cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); + cl_git_pass(git_branch_name(&name, branch)); + cl_assert_equal_s(name, p->first_alternate); + + /* we do not delete the alternate. */ + git_reference_free(branch); + branch = NULL; + + cl_git_fail(git_branch_create(&branch, repo, p->second, target, 0, NULL, NULL)); + git_reference_free(branch); + branch = NULL; + } +} diff --git a/tests/repo/init.c b/tests/repo/init.c index ed86f6e4f..91747c9f5 100644 --- a/tests/repo/init.c +++ b/tests/repo/init.c @@ -714,3 +714,29 @@ void test_repo_init__init_with_initial_commit(void) git_index_free(index); } + +void test_repo_init__at_filesystem_root(void) +{ + git_repository *repo; + const char *sandbox = clar_sandbox_path(); + git_buf root = GIT_BUF_INIT; + int root_len; + + if (!cl_getenv("GITTEST_INVASIVE_FILESYSTEM")) + cl_skip(); + + root_len = git_path_root(sandbox); + cl_assert(root_len >= 0); + + git_buf_put(&root, sandbox, root_len+1); + git_buf_joinpath(&root, root.ptr, "libgit2_test_dir"); + + cl_assert(!git_path_exists(root.ptr)); + + cl_git_pass(git_repository_init(&repo, root.ptr, 0)); + cl_assert(git_path_isdir(root.ptr)); + cl_git_pass(git_futils_rmdir_r(root.ptr, NULL, GIT_RMDIR_REMOVE_FILES)); + + git_buf_free(&root); + git_repository_free(repo); +} |