void test_repo_init__extended_with_template_and_shared_mode(void) { git_buf expected = GIT_BUF_INIT; git_buf actual = GIT_BUF_INIT; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; int filemode = true; const char *repo_path = NULL; cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl"); template_sandbox("template"); opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; opts.template_path = "template"; opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; cl_git_pass(git_repository_init_ext(&_repo, "init_shared_from_tpl", &opts)); cl_assert(!git_repository_is_bare(_repo)); cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/")); filemode = cl_repo_get_bool(_repo, "core.filemode"); cl_git_pass(git_futils_readbuffer( &expected, "template/description")); cl_git_pass(git_futils_readbuffer( &actual, "init_shared_from_tpl/.git/description")); cl_assert_equal_s(expected.ptr, actual.ptr); git_buf_free(&expected); git_buf_free(&actual); repo_path = git_repository_path(_repo); assert_mode_seems_okay(repo_path, "hooks", GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); assert_mode_seems_okay(repo_path, "info", GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); assert_mode_seems_okay(repo_path, "description", GIT_FILEMODE_BLOB, false, filemode); /* for a non-symlinked hook, it should have shared permissions now */ assert_hooks_match( "template", git_repository_path(_repo), "hooks/update.sample", filemode); /* for a symlinked hook, the permissions still should match the * source link, not the GIT_REPOSITORY_INIT_SHARED_GROUP value */ assert_hooks_match( "template", git_repository_path(_repo), "hooks/link.sample", filemode); cl_fixture_cleanup("template"); }
void test_reset_hard__resetting_reverts_modified_files(void) { git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; int i; static const char *files[4] = { "current_file", "modified_file", "staged_new_file", "staged_changes_modified_file" }; static const char *before[4] = { "current_file\n", "modified_file\nmodified_file\n", "staged_new_file\n", "staged_changes_modified_file\nstaged_changes_modified_file\nstaged_changes_modified_file\n" }; static const char *after[4] = { "current_file\n", "modified_file\n", /* wrong value because reset is still slightly incorrect */ "staged_new_file\n", /* right value: NULL, */ "staged_changes_modified_file\n" }; const char *wd = git_repository_workdir(repo); cl_assert(wd); for (i = 0; i < 4; ++i) { cl_git_pass(git_buf_joinpath(&path, wd, files[i])); cl_git_pass(git_futils_readbuffer(&content, path.ptr)); cl_assert_equal_s(before[i], content.ptr); } retrieve_target_from_oid( &target, repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); for (i = 0; i < 4; ++i) { cl_git_pass(git_buf_joinpath(&path, wd, files[i])); if (after[i]) { cl_git_pass(git_futils_readbuffer(&content, path.ptr)); cl_assert(strequal_ignore_eol(after[i], content.ptr)); } else { cl_assert(!git_path_exists(path.ptr)); } } git_buf_free(&content); git_buf_free(&path); }
void test_reset_hard__resetting_reverts_modified_files(void) { git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; int i; static const char *files[4] = { "current_file", "modified_file", "staged_new_file", "staged_changes_modified_file" }; static const char *before[4] = { "current_file\n", "modified_file\nmodified_file\n", "staged_new_file\n", "staged_changes_modified_file\nstaged_changes_modified_file\nstaged_changes_modified_file\n" }; static const char *after[4] = { "current_file\n", "modified_file\n", NULL, "staged_changes_modified_file\n" }; const char *wd = git_repository_workdir(repo); cl_assert(wd); for (i = 0; i < 4; ++i) { cl_git_pass(git_buf_joinpath(&path, wd, files[i])); cl_git_pass(git_futils_readbuffer(&content, path.ptr)); cl_assert_equal_s(before[i], content.ptr); } cl_git_pass(git_revparse_single(&target, repo, "26a125e")); cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL)); for (i = 0; i < 4; ++i) { cl_git_pass(git_buf_joinpath(&path, wd, files[i])); if (after[i]) { cl_git_pass(git_futils_readbuffer(&content, path.ptr)); cl_assert(strequal_ignore_eol(after[i], content.ptr)); } else { cl_assert(!git_path_exists(path.ptr)); } } git_buf_free(&content); git_buf_free(&path); }
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; git_strarray array, *active_refs = NULL; cl_git_pass(git_remote_lookup(&remote, g_repo, "origin")); fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; if(fetchspec != NULL) { array.count = 1; array.strings = (char **) &fetchspec; active_refs = &array; } cl_git_pass(git_remote_fetch(remote, active_refs, &fetch_opts, NULL)); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); git_buf_dispose(&fetchhead_buf); cl_assert(equals); }
static int read_loose(git_rawobj *out, git_buf *loc) { int error; git_buf obj = GIT_BUF_INIT; assert(out && loc); if (git_buf_oom(loc)) return -1; out->data = NULL; out->len = 0; out->type = GIT_OBJ_BAD; if ((error = git_futils_readbuffer(&obj, loc->ptr)) < 0) goto done; if (!is_zlib_compressed_data((unsigned char *)obj.ptr, obj.size)) error = read_loose_packlike(out, &obj); else error = read_loose_standard(out, &obj); done: git_buf_dispose(&obj); return error; }
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; git_strarray array, *active_refs = NULL; cl_git_pass(git_remote_lookup(&remote, g_repo, "origin")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); if(fetchspec != NULL) { array.count = 1; array.strings = (char **) &fetchspec; active_refs = &array; } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(remote, active_refs)); cl_git_pass(git_remote_update_tips(remote, NULL)); git_remote_disconnect(remote); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); git_buf_free(&fetchhead_buf); cl_assert(equals); }
/* * Read the contents of `file_path` and set `path_out` to the repo dir that * it points to. Before calling, set `path_out` to the base directory that * should be used if the contents of `file_path` are a relative path. */ static int read_gitfile(git_buf *path_out, const char *file_path) { int error = 0; git_buf file = GIT_BUF_INIT; size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX); assert(path_out && file_path); if (git_futils_readbuffer(&file, file_path) < 0) return -1; git_buf_rtrim(&file); /* apparently on Windows, some people use backslashes in paths */ git_path_mkposix(file.ptr); if (git_buf_len(&file) <= prefix_len || memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0) { giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path); error = -1; } else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) { const char *gitlink = git_buf_cstr(&file) + prefix_len; while (*gitlink && git__isspace(*gitlink)) gitlink++; error = git_path_prettify_dir( path_out, gitlink, git_buf_cstr(path_out)); } git_buf_free(&file); return error; }
void test_checkout_index__conflicts_honor_coreautocrlf(void) { #ifdef GIT_WIN32 git_index *index; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_buf conflicting_buf = GIT_BUF_INIT; cl_git_pass(p_unlink("./testrepo/.gitattributes")); cl_repo_set_bool(g_repo, "core.autocrlf", true); cl_git_pass(git_repository_index(&index, g_repo)); add_conflict(index, "conflicting.txt"); cl_git_pass(git_index_write(index)); cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt")); cl_assert(strcmp(conflicting_buf.ptr, "<<<<<<< ours\r\n" "this file is changed in master and branch\r\n" "=======\r\n" "this file is changed in branch and master\r\n" ">>>>>>> theirs\r\n") == 0); git_buf_free(&conflicting_buf); git_index_free(index); #endif }
/* * Read the contents of `file_path` and set `path_out` to the repo dir that * it points to. Before calling, set `path_out` to the base directory that * should be used if the contents of `file_path` are a relative path. */ static int read_gitfile(git_buf *path_out, const char *file_path) { int error = 0; git_buf file = GIT_BUF_INIT; size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX); assert(path_out && file_path); if (git_futils_readbuffer(&file, file_path) < 0) return -1; git_buf_rtrim(&file); if (file.size <= prefix_len || memcmp(file.ptr, GIT_FILE_CONTENT_PREFIX, prefix_len) != 0) { giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path); error = -1; } else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) { const char *gitlink = ((const char *)file.ptr) + prefix_len; while (*gitlink && git__isspace(*gitlink)) gitlink++; error = git_path_prettify_dir(path_out, gitlink, path_out->ptr); } git_buf_free(&file); return error; }
static int write_file_filtered( git_oid *oid, git_odb *odb, const char *full_path, git_vector *filters) { int error; git_buf source = GIT_BUF_INIT; git_buf dest = GIT_BUF_INIT; if ((error = git_futils_readbuffer(&source, full_path)) < 0) return error; error = git_filters_apply(&dest, &source, filters); /* Free the source as soon as possible. This can be big in memory, * and we don't want to ODB write to choke */ git_buf_free(&source); /* Write the file to disk if it was properly filtered */ if (!error) error = git_odb_write(oid, odb, dest.ptr, dest.size, GIT_OBJ_BLOB); git_buf_free(&dest); return error; }
void test_config_write__preserves_whitespace_and_comments(void) { const char *file_name = "config-duplicate-header"; const char *n; git_config *cfg; git_buf newfile = GIT_BUF_INIT; /* This config can occur after removing and re-adding the origin remote */ const char *file_content = SECTION_FOO_WITH_COMMENT SECTION_BAR; /* Write the test config and make sure the expected entry exists */ cl_git_mkfile(file_name, file_content); cl_git_pass(git_config_open_ondisk(&cfg, file_name)); cl_git_pass(git_config_set_string(cfg, "section.foo.other", "otherval")); cl_git_pass(git_config_set_string(cfg, "newsection.newname", "new_value")); /* Ensure that we didn't needlessly mangle the config file */ cl_git_pass(git_futils_readbuffer(&newfile, file_name)); n = newfile.ptr; cl_assert_equal_strn(SECTION_FOO, n, strlen(SECTION_FOO)); n += strlen(SECTION_FOO); cl_assert_equal_strn("\tother = otherval\n", n, strlen("\tother = otherval\n")); n += strlen("\tother = otherval\n"); cl_assert_equal_strn(FOO_COMMENT, n, strlen(FOO_COMMENT)); n += strlen(FOO_COMMENT); cl_assert_equal_strn(SECTION_BAR, n, strlen(SECTION_BAR)); n += strlen(SECTION_BAR); cl_assert_equal_s("[newsection]\n\tnewname = new_value\n", n); git_buf_free(&newfile); git_config_free(cfg); }
void test_object_blob_fromchunks__doesnot_overwrite_an_already_existing_object(void) { git_buf path = GIT_BUF_INIT; git_buf content = GIT_BUF_INIT; git_oid expected_oid, oid; int howmany = 7; cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); /* Let's replace the content of the blob file storage with something else... */ cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/32/1cbdf08803c744082332332838df6bd160f8f9")); cl_git_pass(p_unlink(git_buf_cstr(&path))); cl_git_mkfile(git_buf_cstr(&path), "boom"); /* ...request a creation of the same blob... */ howmany = 7; cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); /* ...and ensure the content of the faked blob file hasn't been altered */ cl_git_pass(git_futils_readbuffer(&content, git_buf_cstr(&path))); cl_assert(!git__strcmp("boom", git_buf_cstr(&content))); git_buf_free(&path); git_buf_free(&content); }
void test_repo_init__relative_gitdir(void) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; 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 */ assert_config_entry_value(_repo, "core.worktree", "../c_wd/"); /* 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); cleanup_repository("root"); }
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; cl_git_pass(git_remote_load(&remote, g_repo, "origin")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); if(fetchspec != NULL) { git_remote_clear_refspecs(remote); git_remote_add_fetch(remote, fetchspec); } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); git_buf_free(&fetchhead_buf); cl_assert(equals); }
void test_submodule_repository_init__basic(void) { git_submodule *sm; git_repository *repo; 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_init(sm, 0)); cl_git_pass(git_submodule_repo_init(&repo, sm, 1)); /* Verify worktree */ assert_config_entry_value(repo, "core.worktree", "../../../sm_gitmodules_only/"); /* 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_submodule_free(sm); git_repository_free(repo); git_buf_free(&dot_git_content); }
int git_reference__read_head( git_reference **out, git_repository *repo, const char *path) { git_buf reference = GIT_BUF_INIT; char *name = NULL; int error; if ((error = git_futils_readbuffer(&reference, path)) < 0) goto out; git_buf_rtrim(&reference); if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) == 0) { git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF)); name = git_path_basename(path); if ((*out = git_reference__alloc_symbolic(name, reference.ptr)) == NULL) { error = -1; goto out; } } else { if ((error = git_reference_lookup(out, repo, reference.ptr)) < 0) goto out; } out: git__free(name); git_buf_free(&reference); return error; }
void test_merge_workdir_simple__union(void) { git_buf conflicting_buf = GIT_BUF_INIT; struct merge_index_entry merge_index_entries[] = { ADDED_IN_MASTER_INDEX_ENTRY, AUTOMERGEABLE_INDEX_ENTRY, CHANGED_IN_BRANCH_INDEX_ENTRY, CHANGED_IN_MASTER_INDEX_ENTRY, { 0100644, "72cdb057b340205164478565e91eb71647e66891", 0, "conflicting.txt" }, UNCHANGED_INDEX_ENTRY, }; struct merge_reuc_entry merge_reuc_entries[] = { AUTOMERGEABLE_REUC_ENTRY, CONFLICTING_REUC_ENTRY, REMOVED_IN_BRANCH_REUC_ENTRY, REMOVED_IN_MASTER_REUC_ENTRY }; set_core_autocrlf_to(repo, false); merge_simple_branch(GIT_MERGE_FILE_FAVOR_UNION, 0); cl_git_pass(git_futils_readbuffer(&conflicting_buf, TEST_REPO_PATH "/conflicting.txt")); cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_UNION_FILE) == 0); git_buf_free(&conflicting_buf); cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); }
void test_merge_workdir_simple__diff3(void) { git_buf conflicting_buf = GIT_BUF_INIT; struct merge_index_entry merge_index_entries[] = { ADDED_IN_MASTER_INDEX_ENTRY, AUTOMERGEABLE_INDEX_ENTRY, CHANGED_IN_BRANCH_INDEX_ENTRY, CHANGED_IN_MASTER_INDEX_ENTRY, { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, UNCHANGED_INDEX_ENTRY, }; struct merge_reuc_entry merge_reuc_entries[] = { AUTOMERGEABLE_REUC_ENTRY, REMOVED_IN_BRANCH_REUC_ENTRY, REMOVED_IN_MASTER_REUC_ENTRY }; merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_DIFF3); cl_git_pass(git_futils_readbuffer(&conflicting_buf, TEST_REPO_PATH "/conflicting.txt")); cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0); git_buf_free(&conflicting_buf); cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); }
static int rebase_copy_notes( git_rebase *rebase, const git_signature *committer, const git_rebase_options *opts) { git_buf path = GIT_BUF_INIT, rewritten = GIT_BUF_INIT; char *pair_list, *fromstr, *tostr, *end; git_oid from, to; unsigned int linenum = 1; int error = 0; if (!opts->rewrite_notes_ref) goto done; if ((error = git_buf_joinpath(&path, rebase->state_path, REWRITTEN_FILE)) < 0 || (error = git_futils_readbuffer(&rewritten, path.ptr)) < 0) goto done; pair_list = rewritten.ptr; while (*pair_list) { fromstr = pair_list; if ((end = strchr(fromstr, '\n')) == NULL) goto on_error; pair_list = end+1; *end = '\0'; if ((end = strchr(fromstr, ' ')) == NULL) goto on_error; tostr = end+1; *end = '\0'; if (strlen(fromstr) != GIT_OID_HEXSZ || strlen(tostr) != GIT_OID_HEXSZ || git_oid_fromstr(&from, fromstr) < 0 || git_oid_fromstr(&to, tostr) < 0) goto on_error; if ((error = rebase_copy_note(rebase, &from, &to, committer, opts)) < 0) goto done; linenum++; } goto done; on_error: giterr_set(GITERR_REBASE, "Invalid rewritten file at line %d", linenum); error = -1; done: git_buf_free(&rewritten); git_buf_free(&path); return error; }
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(); /* re-add existing submodule */ cl_git_fail_with( GIT_EEXISTS, git_submodule_add_setup(NULL, g_repo, "whatever", "sm_unchanged", 1)); /* add a submodule using a gitlink */ cl_git_pass( git_submodule_add_setup(&sm, g_repo, "https://github.com/libgit2/libgit2.git", "sm_libgit2", 1) ); git_submodule_free(sm); cl_assert(git_path_isfile("submod2/" "sm_libgit2" "/.git")); cl_assert(git_path_isdir("submod2/.git/modules")); cl_assert(git_path_isdir("submod2/.git/modules/" "sm_libgit2")); 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( git_submodule_add_setup(&sm, g_repo, "https://github.com/libgit2/libgit2.git", "sm_libgit2b", 0) ); git_submodule_free(sm); cl_assert(git_path_isdir("submod2/" "sm_libgit2b" "/.git")); cl_assert(git_path_isfile("submod2/" "sm_libgit2b" "/.git/HEAD")); cl_assert(!git_path_exists("submod2/.git/modules/" "sm_libgit2b")); assert_submodule_url("sm_libgit2b", "https://github.com/libgit2/libgit2.git"); }
void test_merge_workdir_simple__mergefile(void) { git_buf conflicting_buf = GIT_BUF_INIT, mergemsg_buf = GIT_BUF_INIT; struct merge_index_entry merge_index_entries[] = { ADDED_IN_MASTER_INDEX_ENTRY, AUTOMERGEABLE_INDEX_ENTRY, CHANGED_IN_BRANCH_INDEX_ENTRY, CHANGED_IN_MASTER_INDEX_ENTRY, { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, UNCHANGED_INDEX_ENTRY, }; struct merge_reuc_entry merge_reuc_entries[] = { AUTOMERGEABLE_REUC_ENTRY, REMOVED_IN_BRANCH_REUC_ENTRY, REMOVED_IN_MASTER_REUC_ENTRY }; set_core_autocrlf_to(repo, false); merge_simple_branch(0, 0); cl_git_pass(git_futils_readbuffer(&conflicting_buf, TEST_REPO_PATH "/conflicting.txt")); cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_MERGE_FILE) == 0); cl_git_pass(git_futils_readbuffer(&mergemsg_buf, TEST_REPO_PATH "/.git/MERGE_MSG")); cl_assert(strcmp(git_buf_cstr(&mergemsg_buf), "Merge commit '7cb63eed597130ba4abb87b3e544b85021905520'\n" \ "\n" \ "Conflicts:\n" \ "\tconflicting.txt\n") == 0); git_buf_dispose(&conflicting_buf); git_buf_dispose(&mergemsg_buf); cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); }
int git_repository_fetchhead_foreach(git_repository *repo, git_repository_fetchhead_foreach_cb cb, void *payload) { git_buf path = GIT_BUF_INIT, file = GIT_BUF_INIT, name = GIT_BUF_INIT; const char *ref_name; git_oid oid; const char *remote_url; unsigned int is_merge = 0; char *buffer, *line; size_t line_num = 0; int error = 0; assert(repo && cb); if (git_buf_joinpath(&path, repo->path_repository, GIT_FETCH_HEAD_FILE) < 0) return -1; if ((error = git_futils_readbuffer(&file, git_buf_cstr(&path))) < 0) goto done; buffer = file.ptr; while ((line = git__strsep(&buffer, "\n")) != NULL) { ++line_num; if ((error = fetchhead_ref_parse( &oid, &is_merge, &name, &remote_url, line, line_num)) < 0) goto done; if (git_buf_len(&name) > 0) ref_name = git_buf_cstr(&name); else ref_name = NULL; error = cb(ref_name, remote_url, &oid, is_merge, payload); if (error) { giterr_set_after_callback(error); goto done; } } if (*buffer) { giterr_set(GITERR_FETCHHEAD, "No EOL at line %"PRIuZ, line_num+1); error = -1; goto done; } done: git_buf_free(&file); git_buf_free(&path); git_buf_free(&name); return error; }
void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_returns_error(void) { git_reflog *reflog; const git_error *error; const char *refname = "refs/heads/newline"; const char *refmessage = "Reflog*message with a newline and enough content after it to pass the GIT_REFLOG_SIZE_MIN check inside reflog_parse."; git_reference *ref; git_oid id; git_buf logpath = GIT_BUF_INIT, logcontents = GIT_BUF_INIT; char *star; git_oid_fromstr(&id, current_master_tip); /* create a new branch */ cl_git_pass(git_reference_create(&ref, g_repo, refname, &id, 1, refmessage)); /* corrupt the branch reflog by introducing a newline inside the reflog message (we replace '*' with '\n') */ git_buf_join_n(&logpath, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname); cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath))); cl_assert((star = strchr(git_buf_cstr(&logcontents), '*')) != NULL); *star = '\n'; cl_git_rewritefile(git_buf_cstr(&logpath), git_buf_cstr(&logcontents)); /* confirm that the file was rewritten successfully and now contains a '\n' in the expected location */ cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath))); cl_assert(strstr(git_buf_cstr(&logcontents), "Reflog\nmessage") != NULL); /* clear the error state so we can capture the error generated by git_reflog_read */ giterr_clear(); cl_git_fail(git_reflog_read(&reflog, g_repo, refname)); error = giterr_last(); cl_assert(error != NULL); cl_assert_equal_s("unable to parse OID - contains invalid characters", error->message); git_reference_free(ref); git_buf_dispose(&logpath); git_buf_dispose(&logcontents); }
void test_repo_init__extended_with_template(void) { git_buf expected = GIT_BUF_INIT; git_buf actual = GIT_BUF_INIT; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; int filemode; cl_set_cleanup(&cleanup_repository, "templated.git"); template_sandbox("template"); opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; opts.template_path = "template"; cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts)); cl_assert(git_repository_is_bare(_repo)); cl_assert(!git__suffixcmp(git_repository_path(_repo), "/templated.git/")); cl_git_pass(git_futils_readbuffer(&expected, "template/description")); cl_git_pass(git_futils_readbuffer( &actual, "templated.git/description")); cl_assert_equal_s(expected.ptr, actual.ptr); git_buf_free(&expected); git_buf_free(&actual); filemode = cl_repo_get_bool(_repo, "core.filemode"); assert_hooks_match( "template", git_repository_path(_repo), "hooks/update.sample", filemode); assert_hooks_match( "template", git_repository_path(_repo), "hooks/link.sample", filemode); cl_fixture_cleanup("template"); }
static void files_are_equal(const char *a, const char *b) { git_buf buf_a = GIT_BUF_INIT; git_buf buf_b = GIT_BUF_INIT; int pass; if (git_futils_readbuffer(&buf_a, a) < 0) cl_assert(0); if (git_futils_readbuffer(&buf_b, b) < 0) { git_buf_free(&buf_a); cl_assert(0); } pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size)); git_buf_free(&buf_a); git_buf_free(&buf_b); cl_assert(pass); }
static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth) { git_buf alternates_path = GIT_BUF_INIT; git_buf alternates_buf = GIT_BUF_INIT; char *buffer; const char *alternate; int result = 0; /* Git reports an error, we just ignore anything deeper */ if (alternate_depth > GIT_ALTERNATES_MAX_DEPTH) return 0; if (git_buf_joinpath(&alternates_path, objects_dir, GIT_ALTERNATES_FILE) < 0) return -1; if (git_path_exists(alternates_path.ptr) == false) { git_buf_free(&alternates_path); return 0; } if (git_futils_readbuffer(&alternates_buf, alternates_path.ptr) < 0) { git_buf_free(&alternates_path); return -1; } buffer = (char *)alternates_buf.ptr; /* add each alternate as a new backend; one alternate per line */ while ((alternate = git__strtok(&buffer, "\r\n")) != NULL) { if (*alternate == '\0' || *alternate == '#') continue; /* * Relative path: build based on the current `objects` * folder. However, relative paths are only allowed in * the current repository. */ if (*alternate == '.' && !alternate_depth) { if ((result = git_buf_joinpath(&alternates_path, objects_dir, alternate)) < 0) break; alternate = git_buf_cstr(&alternates_path); } if ((result = add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0) break; } git_buf_free(&alternates_path); git_buf_free(&alternates_buf); return result; }
static void ensure_workdir_contents(const char *path, const char *contents) { git_buf fullpath = GIT_BUF_INIT, data_buf = GIT_BUF_INIT; cl_git_pass( git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); cl_git_pass(git_futils_readbuffer(&data_buf, git_buf_cstr(&fullpath))); cl_assert(strcmp(git_buf_cstr(&data_buf), contents) == 0); git_buf_free(&fullpath); git_buf_free(&data_buf); }
void test_checkout_tree__caches_attributes_during_checkout(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid oid; git_object *obj = NULL; git_buf ident1 = GIT_BUF_INIT, ident2 = GIT_BUF_INIT; char *ident_paths[] = { "ident1.txt", "ident2.txt" }; opts.progress_cb = update_attr_callback; assert_on_branch(g_repo, "master"); opts.checkout_strategy = GIT_CHECKOUT_FORCE; opts.paths.strings = ident_paths; opts.paths.count = 2; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/ident")); cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); cl_git_pass(git_futils_readbuffer(&ident1, "testrepo/ident1.txt")); cl_git_pass(git_futils_readbuffer(&ident2, "testrepo/ident2.txt")); cl_assert_equal_strn(ident1.ptr, "# $Id$", 6); cl_assert_equal_strn(ident2.ptr, "# $Id$", 6); cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); cl_git_pass(git_futils_readbuffer(&ident1, "testrepo/ident1.txt")); cl_git_pass(git_futils_readbuffer(&ident2, "testrepo/ident2.txt")); cl_assert_equal_strn(ident1.ptr, "# $Id: ", 7); cl_assert_equal_strn(ident2.ptr, "# $Id: ", 7); git_buf_free(&ident1); git_buf_free(&ident2); git_object_free(obj); }
static void validate_templates(git_repository *repo, const char *template_path) { git_buf template_description = GIT_BUF_INIT; git_buf repo_description = GIT_BUF_INIT; git_buf expected = GIT_BUF_INIT; git_buf actual = GIT_BUF_INIT; int filemode; cl_git_pass(git_buf_joinpath(&template_description, template_path, "description")); cl_git_pass(git_buf_joinpath(&repo_description, git_repository_path(repo), "description")); cl_git_pass(git_futils_readbuffer(&expected, template_description.ptr)); cl_git_pass(git_futils_readbuffer(&actual, repo_description.ptr)); cl_assert_equal_s(expected.ptr, actual.ptr); filemode = cl_repo_get_bool(repo, "core.filemode"); assert_hooks_match( template_path, git_repository_path(repo), "hooks/update.sample", filemode); assert_hooks_match( template_path, git_repository_path(repo), "hooks/link.sample", filemode); assert_hooks_match( template_path, git_repository_path(repo), "hooks/.dotfile", filemode); git_buf_free(&expected); git_buf_free(&actual); git_buf_free(&repo_description); git_buf_free(&template_description); }
void test_config_write__to_file_with_only_comment(void) { git_config *cfg; const char *filename = "config-file"; git_buf result = GIT_BUF_INIT; cl_git_mkfile(filename, "\n\n"); cl_git_pass(git_config_open_ondisk(&cfg, filename)); cl_git_pass(git_config_set_string(cfg, "section.name", "value")); git_config_free(cfg); cl_git_pass(git_futils_readbuffer(&result, "config-file")); cl_assert_equal_s("\n\n[section]\n\tname = value\n", result.ptr); git_buf_free(&result); }