void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standard_one(void) { cl_assert(git_repository_is_bare(repo) == 1); cl_assert(git_repository_workdir(repo) == NULL); cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false)); cl_assert(git_repository_workdir(repo) != NULL); cl_assert(git_repository_is_bare(repo) == 0); }
void test_repo_new__is_bare_until_workdir_set(void) { git_repository *repo; cl_git_pass(git_repository_new(&repo)); cl_assert_equal_b(true, git_repository_is_bare(repo)); cl_git_pass(git_repository_set_workdir(repo, clar_sandbox_path(), 0)); cl_assert_equal_b(false, git_repository_is_bare(repo)); git_repository_free(repo); }
/* * The remote is strictly newer than the local branch. */ static int reset_to_remote(git_repository *repo, git_reference *local, const git_oid *new_id) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_object *target; // If it's not checked out (bare or not HEAD), just update the reference */ if (git_repository_is_bare(repo) || git_branch_is_head(local) != 1) { git_reference *out; if (git_reference_set_target(&out, local, new_id, "Update to remote")) return report_error("Could not update local ref to newer remote ref"); git_reference_free(out); // Not really an error, just informational report_error("Updated local branch from remote"); return 0; } if (git_object_lookup(&target, repo, new_id, GIT_OBJ_COMMIT)) return report_error("Could not look up remote commit"); opts.checkout_strategy = GIT_CHECKOUT_SAFE; if (git_reset(repo, target, GIT_RESET_HARD, &opts)) return report_error("Local head checkout failed after update"); // Not really an error, just informational report_error("Updated local information from remote"); return 0; }
void test_repo_init__extended_with_template_and_shared_mode(void) { 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"); 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); validate_templates(_repo, "template"); cl_fixture_cleanup("template"); }
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 const char *repository_base(git_repository *repo) { if (git_repository_is_bare(repo)) return git_repository_path(repo); return git_repository_workdir(repo); }
/** * Determines whether or not the working directory has non-committed changes. */ static int sync_local_dirty(int *out, git_repository *repo, git_oid *commit_id) { int e = 0; git_tree *tree = NULL; git_diff *diff = NULL; if (git_repository_is_bare(repo)) { *out = 0; goto exit; } git_oid tree_id; git_check(sync_get_tree(&tree_id, repo, commit_id)); git_check(git_tree_lookup(&tree, repo, &tree_id)); git_diff_options diff_options = GIT_DIFF_OPTIONS_INIT; diff_options.flags |= GIT_DIFF_INCLUDE_UNTRACKED; git_check(git_diff_tree_to_workdir(&diff, repo, tree, &diff_options)); *out = git_diff_num_deltas(diff); exit: if (tree) git_tree_free(tree); if (diff) git_diff_free(diff); return e; }
static void ensure_repository_init( const char *working_directory, int is_bare, const char *expected_path_repository, const char *expected_working_directory) { const char *workdir; cl_assert(!git_path_isdir(working_directory)); cl_git_pass(git_repository_init(&_repo, working_directory, is_bare)); workdir = git_repository_workdir(_repo); if (workdir != NULL || expected_working_directory != NULL) { cl_assert( git__suffixcmp(workdir, expected_working_directory) == 0 ); } cl_assert( git__suffixcmp(git_repository_path(_repo), expected_path_repository) == 0 ); cl_assert(git_repository_is_bare(_repo) == is_bare); #ifdef GIT_WIN32 if (!is_bare) { DWORD fattrs = GetFileAttributes(git_repository_path(_repo)); cl_assert((fattrs & FILE_ATTRIBUTE_HIDDEN) != 0); } #endif cl_assert(git_repository_is_empty(_repo)); }
int lg2_status(git_repository *repo, int argc, char *argv[]) { git_status_list *status; struct opts o = { GIT_STATUS_OPTIONS_INIT, "." }; o.statusopt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; o.statusopt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; parse_opts(&o, argc, argv); if (git_repository_is_bare(repo)) fatal("Cannot report status on bare repository", git_repository_path(repo)); show_status: if (o.repeat) printf("\033[H\033[2J"); /** * Run status on the repository * * We use `git_status_list_new()` to generate a list of status * information which lets us iterate over it at our * convenience and extract the data we want to show out of * each entry. * * You can use `git_status_foreach()` or * `git_status_foreach_ext()` if you'd prefer to execute a * callback for each entry. The latter gives you more control * about what results are presented. */ check_lg2(git_status_list_new(&status, repo, &o.statusopt), "Could not get status", NULL); if (o.showbranch) show_branch(repo, o.format); if (o.showsubmod) { int submod_count = 0; check_lg2(git_submodule_foreach(repo, print_submod, &submod_count), "Cannot iterate submodules", o.repodir); } if (o.format == FORMAT_LONG) print_long(status); else print_short(repo, status); git_status_list_free(status); if (o.repeat) { sleep(o.repeat); goto show_status; } return 0; }
PyObject * Repository_is_bare__get__(Repository *self) { if (git_repository_is_bare(self->repo) > 0) Py_RETURN_TRUE; Py_RETURN_FALSE; }
static void env_pass_(const char *path, const char *file, int line) { git_repository *repo; cl_git_expect(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); cl_git_expect(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, 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); }
void test_repo_new__has_nothing(void) { git_repository *repo; cl_git_pass(git_repository_new(&repo)); cl_assert_equal_b(true, git_repository_is_bare(repo)); cl_assert_equal_p(NULL, git_repository_path(repo)); cl_assert_equal_p(NULL, git_repository_workdir(repo)); git_repository_free(repo); }
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"); }
static int create_branch( git_reference **ref_out, git_repository *repository, const char *branch_name, const git_commit *commit, const char *from, int force) { int is_unmovable_head = 0; git_reference *branch = NULL; git_buf canonical_branch_name = GIT_BUF_INIT, log_message = GIT_BUF_INIT; int error = -1; int bare = git_repository_is_bare(repository); assert(branch_name && commit && ref_out); assert(git_object_owner((const git_object *)commit) == repository); if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) { error = git_branch_is_head(branch); git_reference_free(branch); branch = NULL; if (error < 0) goto cleanup; is_unmovable_head = error; } if (is_unmovable_head && force) { giterr_set(GITERR_REFERENCE, "Cannot force update branch '%s' as it is " "the current HEAD of the repository.", branch_name); error = -1; goto cleanup; } if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0) goto cleanup; if (git_buf_printf(&log_message, "branch: Created from %s", from) < 0) goto cleanup; error = git_reference_create(&branch, repository, git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force, git_buf_cstr(&log_message)); if (!error) *ref_out = branch; cleanup: git_buf_free(&canonical_branch_name); git_buf_free(&log_message); return error; }
void test_online_clone__network_full(void) { git_remote *origin; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_assert(!git_repository_is_bare(g_repo)); cl_git_pass(git_remote_lookup(&origin, g_repo, "origin")); cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, origin->download_tags); git_remote_free(origin); }
void test_online_clone__network_bare(void) { git_remote *origin; g_options.bare = true; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_assert(git_repository_is_bare(g_repo)); cl_git_pass(git_remote_lookup(&origin, g_repo, "origin")); git_remote_free(origin); }
void test_reset_hard__cannot_reset_in_a_bare_repository(void) { git_repository *bare; cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git"))); cl_assert(git_repository_is_bare(bare) == true); cl_git_pass(git_revparse_single(&target, bare, KNOWN_COMMIT_IN_BARE_REPO)); cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_HARD, NULL)); git_repository_free(bare); }
void test_reset_mixed__cannot_reset_in_a_bare_repository(void) { git_repository *bare; cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git"))); cl_assert(git_repository_is_bare(bare) == true); retrieve_target_from_oid(&target, bare, KNOWN_COMMIT_IN_BARE_REPO); cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_MIXED)); git_repository_free(bare); }
static int try_to_update(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote, enum remote_transport rt) { git_oid base; const git_oid *local_id, *remote_id; if (!git_reference_cmp(local, remote)) return 0; // Dirty modified state in the working tree? We're not going // to update either way if (git_status_foreach(repo, check_clean, NULL)) return report_error("local cached copy is dirty, skipping update"); local_id = git_reference_target(local); remote_id = git_reference_target(remote); if (!local_id || !remote_id) return report_error("Unable to get local or remote SHA1"); if (git_merge_base(&base, repo, local_id, remote_id)) return report_error("Unable to find common commit of local and remote branches"); /* Is the remote strictly newer? Use it */ if (git_oid_equal(&base, local_id)) return reset_to_remote(repo, local, remote_id); /* Is the local repo the more recent one? See if we can update upstream */ if (git_oid_equal(&base, remote_id)) return update_remote(repo, origin, local, remote, rt); /* Merging a bare repository always needs user action */ if (git_repository_is_bare(repo)) return report_error("Local and remote have diverged, merge of bare branch needed"); /* Merging will definitely need the head branch too */ if (git_branch_is_head(local) != 1) return report_error("Local and remote do not match, local branch not HEAD - cannot update"); /* * Some day we migth try a clean merge here. * * But I couldn't find any good examples of this, so for now * you'd need to merge divergent histories manually. But we've * at least verified above that we have a working tree and the * current branch is checked out and clean, so we *could* try * to merge. */ return report_error("Local and remote have diverged, need to merge"); }
void test_repo_init__extended_with_template(void) { git_repository_init_options opts; memset(&opts, 0, sizeof(opts)); opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE; opts.template_path = cl_fixture("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/")); cleanup_repository("templated.git"); }
void test_checkout_index__target_directory_from_bare(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_index *index; git_object *head = NULL; checkout_counts cts; memset(&cts, 0, sizeof(cts)); test_checkout_index__cleanup(); g_repo = cl_git_sandbox_init("testrepo.git"); cl_assert(git_repository_is_bare(g_repo)); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_revparse_single(&head, g_repo, "HEAD^{tree}")); cl_git_pass(git_index_read_tree(index, (const git_tree *)head)); cl_git_pass(git_index_write(index)); git_index_free(index); opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING; opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; opts.notify_cb = checkout_count_callback; opts.notify_payload = &cts; /* fail to checkout a bare repo */ cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); opts.target_directory = "alternative"; cl_assert(!git_path_isdir("alternative")); cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); cl_assert_equal_i(0, cts.n_untracked); cl_assert_equal_i(0, cts.n_ignored); cl_assert_equal_i(3, cts.n_updates); /* files will have been filtered if needed, so strip CR */ check_file_contents_nocr("./alternative/README", "hey there\n"); check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n"); check_file_contents_nocr("./alternative/new.txt", "my new file\n"); cl_git_pass(git_futils_rmdir_r( "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); git_object_free(head); }
static int checkout_branch(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature, const char *reflog_message) { int error; if (branch) error = update_head_to_branch(repo, git_remote_name(remote), branch, signature, reflog_message); /* Point HEAD to the same ref as the remote's head */ else error = update_head_to_remote(repo, remote, signature, reflog_message); if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts)) error = git_checkout_head(repo, co_opts); return error; }
void test_repo_init__extended_0(void) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; /* without MKDIR this should fail */ cl_git_fail(git_repository_init_ext(&_repo, "extended", &opts)); /* make the directory first, then it should succeed */ cl_git_pass(git_futils_mkdir("extended", 0775, 0)); cl_git_pass(git_repository_init_ext(&_repo, "extended", &opts)); cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/extended/")); cl_assert(!git__suffixcmp(git_repository_path(_repo), "/extended/.git/")); cl_assert(!git_repository_is_bare(_repo)); cl_assert(git_repository_is_empty(_repo)); cleanup_repository("extended"); }
/* * The remote is strictly newer than the local branch. */ static int reset_to_remote(git_repository *repo, git_reference *local, const git_oid *new_id) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.progress_cb = &progress_cb; git_object *target; if (verbose) fprintf(stderr, "git storage: reset to remote\n"); // If it's not checked out (bare or not HEAD), just update the reference */ if (git_repository_is_bare(repo) || git_branch_is_head(local) != 1) { git_reference *out; if (git_reference_set_target(&out, local, new_id, "Update to remote")) return report_error(translate("gettextFromC", "Could not update local cache to newer remote data")); git_reference_free(out); #ifdef DEBUG // Not really an error, just informational report_error("Updated local branch from remote"); #endif return 0; } if (git_object_lookup(&target, repo, new_id, GIT_OBJ_COMMIT)) { if (is_subsurface_cloud) return report_error(translate("gettextFromC", "Subsurface cloud storage corrupted")); else return report_error("Could not look up remote commit"); } opts.checkout_strategy = GIT_CHECKOUT_SAFE; if (git_reset(repo, target, GIT_RESET_HARD, &opts)) { if (is_subsurface_cloud) return report_error(translate("gettextFromC", "Could not update local cache to newer remote data")); else return report_error("Local head checkout failed after update"); } // Not really an error, just informational #ifdef DEBUG report_error("Updated local information from remote"); #endif return 0; }
void test_repo_init__extended_1(void) { git_reference *ref; git_remote *remote; struct stat st; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_NO_DOTGIT_DIR; opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; opts.workdir_path = "../c_wd"; opts.description = "Awesomest test repository evah"; opts.initial_head = "development"; opts.origin_url = "https://github.com/libgit2/libgit2.git"; cl_git_pass(git_repository_init_ext(&_repo, "root/b/c.git", &opts)); cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/c_wd/")); cl_assert(!git__suffixcmp(git_repository_path(_repo), "/c.git/")); cl_assert(git_path_isfile("root/b/c_wd/.git")); cl_assert(!git_repository_is_bare(_repo)); /* repo will not be counted as empty because we set head to "development" */ cl_assert(!git_repository_is_empty(_repo)); cl_git_pass(git_path_lstat(git_repository_path(_repo), &st)); cl_assert(S_ISDIR(st.st_mode)); if (cl_is_chmod_supported()) cl_assert((S_ISGID & st.st_mode) == S_ISGID); else cl_assert((S_ISGID & st.st_mode) == 0); cl_git_pass(git_reference_lookup(&ref, _repo, "HEAD")); cl_assert(git_reference_type(ref) == GIT_REF_SYMBOLIC); cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref)); git_reference_free(ref); cl_git_pass(git_remote_lookup(&remote, _repo, "origin")); cl_assert_equal_s("origin", git_remote_name(remote)); cl_assert_equal_s(opts.origin_url, git_remote_url(remote)); git_remote_free(remote); git_repository_free(_repo); cl_fixture_cleanup("root"); }
/** * Creates a git tree object representing the state of the working directory. */ static int sync_workdir_tree(git_oid *out, git_repository *repo) { int e = 0; git_index *index = NULL; git_check(git_repository_index(&index, repo)); git_check(git_index_clear(index)); git_strarray paths = {NULL, 0}; git_check(git_index_add_all(index, &paths, 0, NULL, NULL)); git_check(git_index_write_tree(out, index)); if (!git_repository_is_bare(repo)) { git_check(git_index_write(index)); } exit: if (index) git_index_free(index); return e; }
/** * Get workdir of repository. * * @param repo S4 class git_repository * @return R_NilValue if bare repository, else character vector * of length one with path. */ SEXP git2r_repository_workdir(SEXP repo) { SEXP result = R_NilValue; git_repository *repository; repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); if (!git_repository_is_bare(repository)) { const char *wd = git_repository_workdir(repository); PROTECT(result = allocVector(STRSXP, 1)); SET_STRING_ELT(result, 0, mkChar(wd)); UNPROTECT(1); } git_repository_free(repository); return result; }
void test_repo_init__external_templates_specified_in_options(void) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; 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/")); validate_templates(_repo, "template"); cl_fixture_cleanup("template"); }
static int try_to_update(git_repository *repo, git_remote *origin, git_reference *local, git_reference *remote, enum remote_transport rt) { git_oid base; const git_oid *local_id, *remote_id; if (!git_reference_cmp(local, remote)) return 0; // Dirty modified state in the working tree? We're not going // to update either way if (git_status_foreach(repo, check_clean, NULL)) return report_error("local cached copy is dirty, skipping update"); local_id = git_reference_target(local); remote_id = git_reference_target(remote); if (!local_id || !remote_id) return report_error("Unable to get local or remote SHA1"); if (git_merge_base(&base, repo, local_id, remote_id)) return report_error("Unable to find common commit of local and remote branches"); /* Is the remote strictly newer? Use it */ if (git_oid_equal(&base, local_id)) return reset_to_remote(repo, local, remote_id); /* Is the local repo the more recent one? See if we can update upstream */ if (git_oid_equal(&base, remote_id)) return update_remote(repo, origin, local, remote, rt); /* Merging a bare repository always needs user action */ if (git_repository_is_bare(repo)) return report_error("Local and remote have diverged, merge of bare branch needed"); /* Merging will definitely need the head branch too */ if (git_branch_is_head(local) != 1) return report_error("Local and remote do not match, local branch not HEAD - cannot update"); /* Ok, let's try to merge these */ return try_to_git_merge(repo, local, remote, &base, local_id, remote_id); }
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"); }