diff options
-rw-r--r-- | .editorconfig | 14 | ||||
-rw-r--r-- | examples/tag.c | 2 | ||||
-rw-r--r-- | include/git2/repository.h | 3 | ||||
-rw-r--r-- | include/git2/submodule.h | 18 | ||||
-rw-r--r-- | src/blame.c | 1 | ||||
-rw-r--r-- | src/pack.c | 3 | ||||
-rw-r--r-- | src/path.c | 55 | ||||
-rw-r--r-- | src/path.h | 11 | ||||
-rw-r--r-- | src/repository.c | 32 | ||||
-rw-r--r-- | src/stash.c | 3 | ||||
-rw-r--r-- | src/submodule.c | 106 | ||||
-rw-r--r-- | src/transports/smart_protocol.c | 2 | ||||
-rw-r--r-- | tests/online/clone.c | 9 | ||||
-rw-r--r-- | tests/path/core.c | 55 | ||||
-rw-r--r-- | tests/repo/init.c | 78 | ||||
-rw-r--r-- | tests/submodule/add.c | 20 | ||||
-rw-r--r-- | tests/submodule/repository_init.c | 40 |
17 files changed, 404 insertions, 48 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..be59274e8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +; Check http://editorconfig.org/ for more informations +; Top-most EditorConfig file +root = true + +; tab indentation +[*] +indent_style = tab +trim_trailing_whitespace = true +insert_final_newline = true + +; 4-column space indentation +[*.md] +indent_style = space +indent_size = 4 diff --git a/examples/tag.c b/examples/tag.c index ebb8e37b2..1d254aee5 100644 --- a/examples/tag.c +++ b/examples/tag.c @@ -236,7 +236,7 @@ static void action_create_tag(tag_state *state) git_signature_free(tagger); } -static void print_usage() +static void print_usage(void) { fprintf(stderr, "usage: see `git help tag`\n"); exit(1); diff --git a/include/git2/repository.h b/include/git2/repository.h index 18e515cb0..268782648 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -196,6 +196,8 @@ GIT_EXTERN(int) git_repository_init( * looking the "template_path" from the options if set, or the * `init.templatedir` global config if not, or falling back on * "/usr/share/git-core/templates" if it exists. + * * GIT_REPOSITORY_INIT_RELATIVE_GITLINK - If an alternate workdir is + * specified, use relative paths for the gitdir and core.worktree. */ typedef enum { GIT_REPOSITORY_INIT_BARE = (1u << 0), @@ -204,6 +206,7 @@ typedef enum { GIT_REPOSITORY_INIT_MKDIR = (1u << 3), GIT_REPOSITORY_INIT_MKPATH = (1u << 4), GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = (1u << 5), + GIT_REPOSITORY_INIT_RELATIVE_GITLINK = (1u << 6), } git_repository_init_flag_t; /** diff --git a/include/git2/submodule.h b/include/git2/submodule.h index 864d1c58c..616890df6 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -471,6 +471,24 @@ GIT_EXTERN(git_submodule_recurse_t) git_submodule_set_fetch_recurse_submodules( GIT_EXTERN(int) git_submodule_init(git_submodule *submodule, int overwrite); /** + * Set up the subrepository for a submodule in preparation for clone. + * + * This function can be called to init and set up a submodule + * repository from a submodule in preparation to clone it from + * its remote. + * + * @param out Output pointer to the created git repository. + * @param sm The submodule to create a new subrepository from. + * @param use_gitlink Should the workdir contain a gitlink to + * the repo in .git/modules vs. repo directly in workdir. + * @return 0 on success, <0 on failure. + */ +GIT_EXTERN(int) git_submodule_repo_init( + git_repository **out, + const git_submodule *sm, + int use_gitlink); + +/** * Copy submodule remote info into submodule repo. * * This copies the information about the submodules URL into the checked out diff --git a/src/blame.c b/src/blame.c index eb977c287..2cc5e552b 100644 --- a/src/blame.c +++ b/src/blame.c @@ -316,7 +316,6 @@ static int blame_internal(git_blame *blame) ent->suspect = o; blame->ent = ent; - blame->path = blame->path; git_blame__like_git(blame, blame->options.flags); diff --git a/src/pack.c b/src/pack.c index b05aa91f1..7c1cfe03e 100644 --- a/src/pack.c +++ b/src/pack.c @@ -648,9 +648,6 @@ int git_packfile_unpack( base_type = elem->type; } - if (error < 0) - goto cleanup; - switch (base_type) { case GIT_OBJ_COMMIT: case GIT_OBJ_TREE: diff --git a/src/path.c b/src/path.c index 77f8d8858..d29b992fe 100644 --- a/src/path.c +++ b/src/path.c @@ -750,6 +750,61 @@ int git_path_cmp( return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0; } +int git_path_make_relative(git_buf *path, const char *parent) +{ + const char *p, *q, *p_dirsep, *q_dirsep; + size_t plen = path->size, newlen, depth = 1, i; + + for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) { + if (*p == '/' && *q == '/') { + p_dirsep = p; + q_dirsep = q; + } + else if (*p != *q) + break; + } + + /* need at least 1 common path segment */ + if ((p_dirsep == path->ptr || q_dirsep == parent) && + (*p_dirsep != '/' || *q_dirsep != '/')) { + giterr_set(GITERR_INVALID, + "%s is not a parent of %s", parent, path->ptr); + return GIT_ENOTFOUND; + } + + if (*p == '/' && !*q) + p++; + else if (!*p && *q == '/') + q++; + else if (!*p && !*q) + return git_buf_clear(path), 0; + else { + p = p_dirsep + 1; + q = q_dirsep + 1; + } + + plen -= (p - path->ptr); + + if (!*q) + return git_buf_set(path, p, plen); + + for (; (q = strchr(q, '/')) && *(q + 1); q++) + depth++; + + newlen = (depth * 3) + plen; + + if (git_buf_try_grow(path, newlen + 1, 1, 0) < 0) + return -1; + + memmove(path->ptr + (depth * 3), p, plen + 1); + + for (i = 0; i < depth; i++) + memcpy(path->ptr + (i * 3), "../", 3); + + path->size = newlen; + return 0; +} + bool git_path_has_non_ascii(const char *path, size_t pathlen) { const uint8_t *scan = (const uint8_t *)path, *end; diff --git a/src/path.h b/src/path.h index 46d6efe93..d0a9de707 100644 --- a/src/path.h +++ b/src/path.h @@ -197,6 +197,17 @@ extern bool git_path_contains(git_buf *dir, const char *item); extern bool git_path_contains_dir(git_buf *parent, const char *subdir); /** + * Make the path relative to the given parent path. + * + * @param path The path to make relative + * @param parent The parent path to make path relative to + * @return 0 if path was made relative, GIT_ENOTFOUND + * if there was not common root between the paths, + * or <0. + */ +extern int git_path_make_relative(git_buf *path, const char *parent); + +/** * Check if the given path contains the given file. * * @param dir Directory path that might contain file diff --git a/src/repository.c b/src/repository.c index 4f7a5feab..d86d8905a 100644 --- a/src/repository.c +++ b/src/repository.c @@ -994,7 +994,7 @@ static int repo_init_config( uint32_t mode) { int error = 0; - git_buf cfg_path = GIT_BUF_INIT; + git_buf cfg_path = GIT_BUF_INIT, worktree_path = GIT_BUF_INIT; git_config *config = NULL; bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0); @@ -1019,9 +1019,16 @@ static int repo_init_config( if (!is_bare) { SET_REPO_CONFIG(bool, "core.logallrefupdates", true); - if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) - SET_REPO_CONFIG(string, "core.worktree", work_dir); - else if (is_reinit) { + if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { + if ((error = git_buf_sets(&worktree_path, work_dir)) < 0) + goto cleanup; + + if ((flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK)) + if ((error = git_path_make_relative(&worktree_path, repo_dir)) < 0) + goto cleanup; + + SET_REPO_CONFIG(string, "core.worktree", worktree_path.ptr); + } else if (is_reinit) { if (git_config_delete_entry(config, "core.worktree") < 0) giterr_clear(); } @@ -1038,6 +1045,7 @@ static int repo_init_config( cleanup: git_buf_free(&cfg_path); + git_buf_free(&worktree_path); git_config_free(config); return error; @@ -1126,10 +1134,11 @@ static int repo_write_template( } static int repo_write_gitlink( - const char *in_dir, const char *to_repo) + const char *in_dir, const char *to_repo, bool use_relative_path) { int error; git_buf buf = GIT_BUF_INIT; + git_buf path_to_repo = GIT_BUF_INIT; struct stat st; git_path_dirname_r(&buf, to_repo); @@ -1157,13 +1166,20 @@ static int repo_write_gitlink( git_buf_clear(&buf); - error = git_buf_printf(&buf, "%s %s", GIT_FILE_CONTENT_PREFIX, to_repo); + error = git_buf_sets(&path_to_repo, to_repo); + + if (!error && use_relative_path) + error = git_path_make_relative(&path_to_repo, in_dir); + + if (!error) + error = git_buf_join(&buf, ' ', GIT_FILE_CONTENT_PREFIX, path_to_repo.ptr); if (!error) error = repo_write_template(in_dir, true, DOT_GIT, 0666, true, buf.ptr); cleanup: git_buf_free(&buf); + git_buf_free(&path_to_repo); return error; } @@ -1207,7 +1223,7 @@ static int repo_init_structure( if ((opts->flags & GIT_REPOSITORY_INIT_BARE) == 0 && (opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD) == 0) { - if (repo_write_gitlink(work_dir, repo_dir) < 0) + if (repo_write_gitlink(work_dir, repo_dir, opts->flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK) < 0) return -1; } @@ -1635,7 +1651,7 @@ int git_repository_set_workdir( if (git_repository_config__weakptr(&config, repo) < 0) return -1; - error = repo_write_gitlink(path.ptr, git_repository_path(repo)); + error = repo_write_gitlink(path.ptr, git_repository_path(repo), false); /* passthrough error means gitlink is unnecessary */ if (error == GIT_PASSTHROUGH) diff --git a/src/stash.c b/src/stash.c index 86e0a627c..22f756e35 100644 --- a/src/stash.c +++ b/src/stash.c @@ -634,7 +634,8 @@ int git_stash_drop( entry = git_reflog_entry_byindex(reflog, 0); git_reference_free(stash); - if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1, NULL, NULL) < 0)) + error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, &entry->oid_cur, 1, NULL, NULL); + if (error < 0) goto cleanup; /* We need to undo the writing that we just did */ diff --git a/src/submodule.c b/src/submodule.c index b1291df8e..ccc8ad117 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -306,6 +306,56 @@ void git_submodule_cache_free(git_repository *repo) submodule_cache_free(cache); } +static int submodule_repo_init( + git_repository **out, + git_repository *parent_repo, + const char *path, + const char *url, + bool use_gitlink) +{ + int error = 0; + git_buf workdir = GIT_BUF_INIT, repodir = GIT_BUF_INIT; + git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_repository *subrepo = NULL; + + error = git_buf_joinpath(&workdir, git_repository_workdir(parent_repo), path); + if (error < 0) + goto cleanup; + + initopt.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_REINIT; + initopt.origin_url = url; + + /* init submodule repository and add origin remote as needed */ + + /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a + * gitlink in the sub-repo workdir directory to that repository + * + * Old style: sub-repo goes directly into repo/<name>/.git/ + */ + if (use_gitlink) { + error = git_buf_join3( + &repodir, '/', git_repository_path(parent_repo), "modules", path); + if (error < 0) + goto cleanup; + + initopt.workdir_path = workdir.ptr; + initopt.flags |= + GIT_REPOSITORY_INIT_NO_DOTGIT_DIR | + GIT_REPOSITORY_INIT_RELATIVE_GITLINK; + + error = git_repository_init_ext(&subrepo, repodir.ptr, &initopt); + } else + error = git_repository_init_ext(&subrepo, workdir.ptr, &initopt); + +cleanup: + git_buf_free(&workdir); + git_buf_free(&repodir); + + *out = subrepo; + + return error; +} + int git_submodule_add_setup( git_submodule **out, git_repository *repo, @@ -317,7 +367,6 @@ int git_submodule_add_setup( git_config_backend *mods = NULL; git_submodule *sm = NULL; git_buf name = GIT_BUF_INIT, real_url = GIT_BUF_INIT; - git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT; git_repository *subrepo = NULL; assert(repo && url && path); @@ -371,41 +420,14 @@ int git_submodule_add_setup( if (error < 0) goto cleanup; - /* New style: sub-repo goes in <repo-dir>/modules/<name>/ with a - * gitlink in the sub-repo workdir directory to that repository - * - * Old style: sub-repo goes directly into repo/<name>/.git/ + /* if the repo does not already exist, then init a new repo and add it. + * Otherwise, just add the existing repo. */ - - initopt.flags = GIT_REPOSITORY_INIT_MKPATH | - GIT_REPOSITORY_INIT_NO_REINIT; - initopt.origin_url = real_url.ptr; - - if (git_path_exists(name.ptr) && - git_path_contains(&name, DOT_GIT)) - { - /* repo appears to already exist - reinit? */ - } - else if (use_gitlink) { - git_buf repodir = GIT_BUF_INIT; - - error = git_buf_join3( - &repodir, '/', git_repository_path(repo), "modules", path); - if (error < 0) + if (!(git_path_exists(name.ptr) && + git_path_contains(&name, DOT_GIT))) { + if ((error = submodule_repo_init(&subrepo, repo, path, real_url.ptr, use_gitlink)) < 0) goto cleanup; - - initopt.workdir_path = name.ptr; - initopt.flags |= GIT_REPOSITORY_INIT_NO_DOTGIT_DIR; - - error = git_repository_init_ext(&subrepo, repodir.ptr, &initopt); - - git_buf_free(&repodir); } - else { - error = git_repository_init_ext(&subrepo, name.ptr, &initopt); - } - if (error < 0) - goto cleanup; /* add submodule to hash and "reload" it */ @@ -437,6 +459,23 @@ cleanup: return error; } +int git_submodule_repo_init( + git_repository **out, + const git_submodule *sm, + int use_gitlink) +{ + int error; + git_repository *sub_repo = NULL; + + assert(out && sm); + + error = submodule_repo_init(&sub_repo, sm->repo, sm->path, sm->url, use_gitlink); + + *out = sub_repo; + + return error; +} + int git_submodule_add_finalize(git_submodule *sm) { int error; @@ -1897,6 +1936,7 @@ static void submodule_get_index_status(unsigned int *status, git_submodule *sm) *status |= GIT_SUBMODULE_STATUS_INDEX_MODIFIED; } + static void submodule_get_wd_status( unsigned int *status, git_submodule *sm, diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 82891165f..5ca5065ac 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -314,7 +314,7 @@ static int wait_while_ack(gitno_buffer *buf) break; if (pkt->type == GIT_PKT_ACK && - (pkt->status != GIT_ACK_CONTINUE || + (pkt->status != GIT_ACK_CONTINUE && pkt->status != GIT_ACK_COMMON)) { git__free(pkt); return 0; diff --git a/tests/online/clone.c b/tests/online/clone.c index 1ccaf2773..6a6c049f8 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -384,6 +384,9 @@ void test_online_clone__ssh_auth_methods(void) { int with_user; +#ifndef GIT_SSH + clar__skip(); +#endif g_options.remote_callbacks.credentials = check_ssh_auth_methods; g_options.remote_callbacks.payload = &with_user; @@ -436,6 +439,9 @@ void test_online_clone__ssh_with_paths(void) const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); const char *remote_user = cl_getenv("GITTEST_REMOTE_USER"); +#ifndef GIT_SSH + clar__skip(); +#endif if (!remote_url || !remote_user || strncmp(remote_url, "ssh://", 5) != 0) clar__skip(); @@ -459,6 +465,9 @@ static int cred_foo_bar(git_cred **cred, const char *url, const char *username_f void test_online_clone__ssh_cannot_change_username(void) { +#ifndef GIT_SSH + clar__skip(); +#endif g_options.remote_callbacks.credentials = cred_foo_bar; cl_git_fail(git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options)); diff --git a/tests/path/core.c b/tests/path/core.c new file mode 100644 index 000000000..be63e309b --- /dev/null +++ b/tests/path/core.c @@ -0,0 +1,55 @@ +#include "clar_libgit2.h" +#include "path.h" + +static void test_make_relative( + const char *expected_path, + const char *path, + const char *parent, + int expected_status) +{ + git_buf buf = GIT_BUF_INIT; + git_buf_puts(&buf, path); + cl_assert_equal_i(expected_status, git_path_make_relative(&buf, parent)); + cl_assert_equal_s(expected_path, buf.ptr); + git_buf_free(&buf); +} + +void test_path_core__make_relative(void) +{ + git_buf buf = GIT_BUF_INIT; + + test_make_relative("foo.c", "/path/to/foo.c", "/path/to", 0); + test_make_relative("bar/foo.c", "/path/to/bar/foo.c", "/path/to", 0); + test_make_relative("foo.c", "/path/to/foo.c", "/path/to/", 0); + + test_make_relative("", "/path/to", "/path/to", 0); + test_make_relative("", "/path/to", "/path/to/", 0); + + test_make_relative("../", "/path/to", "/path/to/foo", 0); + + test_make_relative("../foo.c", "/path/to/foo.c", "/path/to/bar", 0); + test_make_relative("../bar/foo.c", "/path/to/bar/foo.c", "/path/to/baz", 0); + + test_make_relative("../../foo.c", "/path/to/foo.c", "/path/to/foo/bar", 0); + test_make_relative("../../foo/bar.c", "/path/to/foo/bar.c", "/path/to/bar/foo", 0); + + test_make_relative("../../foo.c", "/foo.c", "/bar/foo", 0); + + test_make_relative("foo.c", "/path/to/foo.c", "/path/to/", 0); + test_make_relative("../foo.c", "/path/to/foo.c", "/path/to/bar/", 0); + + test_make_relative("foo.c", "d:/path/to/foo.c", "d:/path/to", 0); + + test_make_relative("../foo", "/foo", "/bar", 0); + test_make_relative("path/to/foo.c", "/path/to/foo.c", "/", 0); + test_make_relative("../foo", "path/to/foo", "path/to/bar", 0); + + test_make_relative("/path/to/foo.c", "/path/to/foo.c", "d:/path/to", GIT_ENOTFOUND); + test_make_relative("d:/path/to/foo.c", "d:/path/to/foo.c", "/path/to", GIT_ENOTFOUND); + + test_make_relative("/path/to/foo.c", "/path/to/foo.c", "not-a-rooted-path", GIT_ENOTFOUND); + test_make_relative("not-a-rooted-path", "not-a-rooted-path", "/path/to", GIT_ENOTFOUND); + + test_make_relative("/path", "/path", "pathtofoo", GIT_ENOTFOUND); + test_make_relative("path", "path", "pathtofoo", GIT_ENOTFOUND); +} diff --git a/tests/repo/init.c b/tests/repo/init.c index aea383c64..999afd625 100644 --- a/tests/repo/init.c +++ b/tests/repo/init.c @@ -367,6 +367,84 @@ void test_repo_init__extended_1(void) cl_fixture_cleanup("root"); } +void test_repo_init__relative_gitdir(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_config *cfg; + const char *worktree_path; + git_buf dot_git_content = GIT_BUF_INIT; + + opts.workdir_path = "../c_wd"; + opts.flags = + GIT_REPOSITORY_INIT_MKPATH | + GIT_REPOSITORY_INIT_RELATIVE_GITLINK | + GIT_REPOSITORY_INIT_NO_DOTGIT_DIR; + + /* make the directory first, then it should succeed */ + cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts)); + + cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/")); + cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/")); + cl_assert(!git_repository_is_bare(_repo)); + cl_assert(git_repository_is_empty(_repo)); + + /* Verify that the gitlink and worktree entries are relative */ + + /* Verify worktree */ + cl_git_pass(git_repository_config(&cfg, _repo)); + cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); + cl_assert_equal_s("../c_wd/", worktree_path); + + /* Verify gitlink */ + cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git")); + cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr); + + git_buf_free(&dot_git_content); + git_config_free(cfg); + cleanup_repository("root"); +} + +void test_repo_init__relative_gitdir_2(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_config *cfg; + const char *worktree_path; + git_buf dot_git_content = GIT_BUF_INIT; + git_buf full_path = GIT_BUF_INIT; + + cl_git_pass(git_path_prettify(&full_path, ".", NULL)); + cl_git_pass(git_buf_joinpath(&full_path, full_path.ptr, "root/b/c_wd")); + + opts.workdir_path = full_path.ptr; + opts.flags = + GIT_REPOSITORY_INIT_MKPATH | + GIT_REPOSITORY_INIT_RELATIVE_GITLINK | + GIT_REPOSITORY_INIT_NO_DOTGIT_DIR; + + /* make the directory first, then it should succeed */ + cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts)); + + cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/")); + cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/")); + cl_assert(!git_repository_is_bare(_repo)); + cl_assert(git_repository_is_empty(_repo)); + + /* Verify that the gitlink and worktree entries are relative */ + + /* Verify worktree */ + cl_git_pass(git_repository_config(&cfg, _repo)); + cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); + cl_assert_equal_s("../c_wd/", worktree_path); + + /* Verify gitlink */ + cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git")); + cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr); + + git_buf_free(&dot_git_content); + git_config_free(cfg); + cleanup_repository("root"); +} + #define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177) static void assert_hooks_match( diff --git a/tests/submodule/add.c b/tests/submodule/add.c index 9fdc7cc57..10717809e 100644 --- a/tests/submodule/add.c +++ b/tests/submodule/add.c @@ -2,6 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" +#include "fileops.h" static git_repository *g_repo = NULL; @@ -29,6 +30,10 @@ static void assert_submodule_url(const char* name, const char *url) void test_submodule_add__url_absolute(void) { git_submodule *sm; + git_config *cfg; + git_repository *repo; + const char *worktree_path; + git_buf dot_git_content = GIT_BUF_INIT; g_repo = setup_fixture_submod2(); @@ -51,6 +56,21 @@ void test_submodule_add__url_absolute(void) cl_assert(git_path_isfile("submod2/.git/modules/" "sm_libgit2" "/HEAD")); assert_submodule_url("sm_libgit2", "https://github.com/libgit2/libgit2.git"); + cl_git_pass(git_repository_open(&repo, "submod2/" "sm_libgit2")); + + /* Verify worktree path is relative */ + cl_git_pass(git_repository_config(&cfg, repo)); + cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); + cl_assert_equal_s("../../../sm_libgit2/", worktree_path); + + /* Verify gitdir path is relative */ + cl_git_pass(git_futils_readbuffer(&dot_git_content, "submod2/" "sm_libgit2" "/.git")); + cl_assert_equal_s("gitdir: ../.git/modules/sm_libgit2/", dot_git_content.ptr); + + git_config_free(cfg); + git_repository_free(repo); + git_buf_free(&dot_git_content); + /* add a submodule not using a gitlink */ cl_git_pass( diff --git a/tests/submodule/repository_init.c b/tests/submodule/repository_init.c new file mode 100644 index 000000000..24b47aff8 --- /dev/null +++ b/tests/submodule/repository_init.c @@ -0,0 +1,40 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "path.h" +#include "submodule_helpers.h" +#include "fileops.h" + +static git_repository *g_repo = NULL; + +void test_submodule_repository_init__basic(void) +{ + git_submodule *sm; + git_repository *repo; + git_config *cfg; + const char *worktree_path; + git_buf dot_git_content = GIT_BUF_INIT; + + g_repo = setup_fixture_submod2(); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); + cl_git_pass(git_submodule_repo_init(&repo, sm, 1)); + + /* Verify worktree */ + cl_git_pass(git_repository_config(&cfg, repo)); + cl_git_pass(git_config_get_string(&worktree_path, cfg, "core.worktree")); + cl_assert_equal_s("../../../sm_gitmodules_only/", worktree_path); + + /* Verify gitlink */ + cl_git_pass(git_futils_readbuffer(&dot_git_content, "submod2/" "sm_gitmodules_only" "/.git")); + cl_assert_equal_s("gitdir: ../.git/modules/sm_gitmodules_only/", dot_git_content.ptr); + + cl_assert(git_path_isfile("submod2/" "sm_gitmodules_only" "/.git")); + + cl_assert(git_path_isdir("submod2/.git/modules")); + cl_assert(git_path_isdir("submod2/.git/modules/" "sm_gitmodules_only")); + cl_assert(git_path_isfile("submod2/.git/modules/" "sm_gitmodules_only" "/HEAD")); + + git_config_free(cfg); + git_repository_free(repo); + git_buf_free(&dot_git_content); +} |