void test_checkout_crlf__autocrlf_input_no_attrs(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_repo_set_string(g_repo, "core.autocrlf", "input"); git_checkout_head(g_repo, &opts); check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); }
void test_checkout_crlf__detect_crlf_autocrlf_false(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_repo_set_bool(g_repo, "core.autocrlf", false); git_checkout_head(g_repo, &opts); check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); }
void test_checkout_tree__can_remove_untracked(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_UNTRACKED; cl_git_mkfile("testrepo/untracked_file", "as you wish"); cl_assert(git_path_isfile("testrepo/untracked_file")); cl_git_pass(git_checkout_head(g_repo, &opts)); cl_assert(!git_path_isfile("testrepo/untracked_file")); }
void test_checkout_crlf__more_crlf_autocrlf_true(void) { git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; cl_repo_set_bool(g_repo, "core.autocrlf", true); git_checkout_head(g_repo, &opts); if (GIT_EOL_NATIVE == GIT_EOL_LF) check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW); else check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_AS_CRLF); }
/** * Checks out the given branch. */ static int sync_checkout(git_repository *repo, const char *name) { int e = 0; git_check(git_repository_set_head(repo, name)); git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; git_check(git_checkout_head(repo, &opts)); exit: return e; }
/* git checkout beef && git rebase --merge --onto `git rev-parse master` * `git rev-parse veal` `git rev-parse gravy` */ void test_rebase_setup__merge_onto_upstream_and_branch_by_id(void) { git_rebase *rebase; git_oid upstream_id, branch_id, onto_id; git_annotated_commit *upstream_head, *branch_head, *onto_head; git_reference *head; git_commit *head_commit; git_oid head_id; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_git_pass(git_repository_set_head(repo, "refs/heads/beef")); cl_git_pass(git_checkout_head(repo, &checkout_opts)); cl_git_pass(git_oid_fromstr(&upstream_id, "f87d14a4a236582a0278a916340a793714256864")); cl_git_pass(git_oid_fromstr(&branch_id, "d616d97082eb7bb2dc6f180a7cca940993b7a56f")); cl_git_pass(git_oid_fromstr(&onto_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00")); cl_git_pass(git_annotated_commit_lookup(&upstream_head, repo, &upstream_id)); cl_git_pass(git_annotated_commit_lookup(&branch_head, repo, &branch_id)); cl_git_pass(git_annotated_commit_lookup(&onto_head, repo, &onto_id)); cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, onto_head, NULL)); git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJECT_COMMIT)); cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); cl_assert_equal_file("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n", 41, "rebase/.git/ORIG_HEAD"); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); cl_assert_equal_file("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n", 41, "rebase/.git/rebase-merge/cmt.1"); cl_assert_equal_file("1\n", 2, "rebase/.git/rebase-merge/end"); cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto_name"); cl_assert_equal_file("d616d97082eb7bb2dc6f180a7cca940993b7a56f\n", 41, "rebase/.git/rebase-merge/orig-head"); git_commit_free(head_commit); git_reference_free(head); git_annotated_commit_free(upstream_head); git_annotated_commit_free(branch_head); git_annotated_commit_free(onto_head); git_rebase_free(rebase); }
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; }
/* git checkout beef && git rebase --merge master */ void test_rebase_setup__merge_null_branch_uses_HEAD(void) { git_rebase *rebase; git_reference *upstream_ref; git_annotated_commit *upstream_head; git_reference *head; git_commit *head_commit; git_oid head_id; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_assert_equal_i(GIT_REPOSITORY_STATE_NONE, git_repository_state(repo)); cl_git_pass(git_repository_set_head(repo, "refs/heads/beef")); cl_git_pass(git_checkout_head(repo, &checkout_opts)); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); cl_git_pass(git_rebase_init(&rebase, repo, NULL, upstream_head, NULL, NULL)); cl_assert_equal_i(GIT_REPOSITORY_STATE_REBASE_MERGE, git_repository_state(repo)); git_oid_fromstr(&head_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_reference_peel((git_object **)&head_commit, head, GIT_OBJECT_COMMIT)); cl_assert_equal_oid(&head_id, git_commit_id(head_commit)); cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/ORIG_HEAD"); cl_assert_equal_file("da9c51a23d02d931a486f45ad18cda05cf5d2b94\n", 41, "rebase/.git/rebase-merge/cmt.1"); cl_assert_equal_file("8d1f13f93c4995760ac07d129246ac1ff64c0be9\n", 41, "rebase/.git/rebase-merge/cmt.2"); cl_assert_equal_file("3069cc907e6294623e5917ef6de663928c1febfb\n", 41, "rebase/.git/rebase-merge/cmt.3"); cl_assert_equal_file("588e5d2f04d49707fe4aab865e1deacaf7ef6787\n", 41, "rebase/.git/rebase-merge/cmt.4"); cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/rebase-merge/cmt.5"); cl_assert_equal_file("5\n", 2, "rebase/.git/rebase-merge/end"); cl_assert_equal_file("efad0b11c47cb2f0220cbd6f5b0f93bb99064b00\n", 41, "rebase/.git/rebase-merge/onto"); cl_assert_equal_file("master\n", 7, "rebase/.git/rebase-merge/onto_name"); cl_assert_equal_file("b146bd7608eac53d9bf9e1a6963543588b555c64\n", 41, "rebase/.git/rebase-merge/orig-head"); git_commit_free(head_commit); git_reference_free(head); git_annotated_commit_free(upstream_head); git_reference_free(upstream_ref); git_rebase_free(rebase); }
void test_checkout_crlf__autocrlf_true_no_attrs(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_repo_set_bool(g_repo, "core.autocrlf", true); git_checkout_head(g_repo, &opts); if (GIT_EOL_NATIVE == GIT_EOL_CRLF) { check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF); check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF); } else { check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); } }
PyObject * Repository_checkout_head(Repository *self, PyObject *args) { git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; unsigned int strategy; int err; if (!PyArg_ParseTuple(args, "I", &strategy)) return NULL; opts.checkout_strategy = strategy; err = git_checkout_head(self->repo, &opts); if (err < 0) return Error_set(err); Py_RETURN_NONE; }
int git_clone( git_repository **out, const char *url, const char *local_path, const git_clone_options *options) { int retcode = GIT_ERROR; git_repository *repo = NULL; git_clone_options normOptions; int remove_directory_on_failure = 0; assert(out && url && local_path); normalize_options(&normOptions, options); GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); if (!path_is_okay(local_path)) { return GIT_ERROR; } /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); if (!(retcode = git_repository_init(&repo, local_path, normOptions.bare))) { if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { /* Failed to fetch; clean up */ git_repository_free(repo); if (remove_directory_on_failure) git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); else git_futils_cleanupdir_r(local_path); } else { *out = repo; retcode = 0; } } if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts)) retcode = git_checkout_head(*out, &normOptions.checkout_opts); return retcode; }
void test_checkout_crlf__autocrlf_false_text_auto_attr(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n"); cl_repo_set_bool(g_repo, "core.autocrlf", false); git_checkout_head(g_repo, &opts); if (GIT_EOL_NATIVE == GIT_EOL_CRLF) { check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF); check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF); } else { check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); } }
void test_checkout_crlf__can_write_empty_file(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_repo_set_bool(g_repo, "core.autocrlf", true); git_repository_set_head(g_repo, "refs/heads/empty-files"); git_checkout_head(g_repo, &opts); check_file_contents("./crlf/test1.txt", ""); if (GIT_EOL_NATIVE == GIT_EOL_LF) check_file_contents("./crlf/test2.txt", "test2.txt's content\n"); else check_file_contents("./crlf/test2.txt", "test2.txt's content\r\n"); check_file_contents("./crlf/test3.txt", ""); }
void test_checkout_tree__can_remove_ignored(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; int ignored = 0; opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_IGNORED; cl_git_mkfile("testrepo/ignored_file", "as you wish"); cl_git_pass(git_ignore_add_rule(g_repo, "ignored_file\n")); cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "ignored_file")); cl_assert_equal_i(1, ignored); cl_assert(git_path_isfile("testrepo/ignored_file")); cl_git_pass(git_checkout_head(g_repo, &opts)); cl_assert(!git_path_isfile("testrepo/ignored_file")); }
void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void) { git_index *index; const git_index_entry *entry; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_repo_set_bool(g_repo, "core.autocrlf", false); git_checkout_head(g_repo, &opts); git_repository_index(&index, g_repo); cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); cl_assert(entry->file_size == strlen(ALL_LF_TEXT_RAW)); cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL); cl_assert(entry->file_size == strlen(ALL_CRLF_TEXT_RAW)); git_index_free(index); }
void test_checkout_tree__can_update_only(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_oid oid; git_object *obj = NULL; /* first let's get things into a known state - by checkout out the HEAD */ assert_on_branch(g_repo, "master"); opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_checkout_head(g_repo, &opts)); cl_assert(!git_path_isdir("testrepo/a")); check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n"); /* now checkout branch but with update only */ opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); 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_repository_set_head(g_repo, "refs/heads/dir")); assert_on_branch(g_repo, "dir"); /* this normally would have been created (which was tested separately in * the test_checkout_tree__can_switch_branches test), but with * UPDATE_ONLY it will not have been created. */ cl_assert(!git_path_isdir("testrepo/a")); /* but this file still should have been updated */ check_file_contents_nocr("testrepo/branch_file.txt", "hi\n"); git_object_free(obj); }
int merge_branches(git_merge_result **result, git_repository *repo, const char *ours_branch, const char *theirs_branch, git_merge_opts *opts) { git_reference *head_ref, *theirs_ref; git_merge_head *theirs_head; git_checkout_opts head_checkout_opts = GIT_CHECKOUT_OPTS_INIT; head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1)); cl_git_pass(git_checkout_head(repo, &head_checkout_opts)); cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref)); cl_git_pass(git_merge(result, repo, (const git_merge_head **)&theirs_head, 1, opts)); git_reference_free(head_ref); git_reference_free(theirs_ref); git_merge_head_free(theirs_head); return 0; }
int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; size_t nspecs; assert(repo && remote); if (!git_repository_is_empty(repo)) { giterr_set(GITERR_INVALID, "the repository is not empty"); return -1; } if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) return error; old_fetchhead = git_remote_update_fetchhead(remote); git_remote_set_update_fetchhead(remote, 0); if ((error = git_remote_fetch(remote)) < 0) goto cleanup; if (branch) error = update_head_to_branch(repo, git_remote_name(remote), branch); /* Point HEAD to the same ref as the remote's head */ else error = update_head_to_remote(repo, remote); if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts)) error = git_checkout_head(repo, co_opts); cleanup: git_remote_set_update_fetchhead(remote, old_fetchhead); /* Remove the tags refspec */ nspecs = git_remote_refspec_count(remote); git_remote_remove_refspec(remote, nspecs); return error; }
int merge_branches(git_repository *repo, const char *ours_branch, const char *theirs_branch, git_merge_options *merge_opts, git_checkout_options *checkout_opts) { git_reference *head_ref, *theirs_ref; git_annotated_commit *theirs_head; git_checkout_options head_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1, NULL)); cl_git_pass(git_checkout_head(repo, &head_checkout_opts)); cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); cl_git_pass(git_annotated_commit_from_ref(&theirs_head, repo, theirs_ref)); cl_git_pass(git_merge(repo, (const git_annotated_commit **)&theirs_head, 1, merge_opts, checkout_opts)); git_reference_free(head_ref); git_reference_free(theirs_ref); git_annotated_commit_free(theirs_head); return 0; }
void GitRepository::branch(const QString& name) { git_repository* repo = repository(); git_auto<git_reference> branch; int err = git_branch_lookup(&branch, repo, name.toLatin1(), GIT_BRANCH_LOCAL); if (err == GIT_ENOTFOUND){ git_oid parent_id; git_auto<git_commit> parent; git_eval(git_reference_name_to_id(&parent_id, repo, "HEAD")); git_eval(git_commit_lookup(&parent, repo, &parent_id)); git_eval(git_branch_create(&branch, repo, name.toLocal8Bit(), parent, 1)); }else{ git_eval(err); } git_eval(git_repository_set_head(repo, git_reference_name(branch))); git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; git_eval(git_checkout_head(repo, &opts)); }
void test_checkout_crlf__detect_crlf_autocrlf_true_utf8(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_repo_set_bool(g_repo, "core.autocrlf", true); git_repository_set_head(g_repo, "refs/heads/utf8"); git_checkout_head(g_repo, &opts); if (GIT_EOL_NATIVE == GIT_EOL_LF) { check_file_contents("./crlf/few-utf8-chars-lf.txt", FEW_UTF8_LF_RAW); check_file_contents("./crlf/many-utf8-chars-lf.txt", MANY_UTF8_LF_RAW); } else { check_file_contents("./crlf/few-utf8-chars-lf.txt", FEW_UTF8_CRLF_RAW); check_file_contents("./crlf/many-utf8-chars-lf.txt", MANY_UTF8_CRLF_RAW); } check_file_contents("./crlf/few-utf8-chars-crlf.txt", FEW_UTF8_CRLF_RAW); check_file_contents("./crlf/many-utf8-chars-crlf.txt", MANY_UTF8_CRLF_RAW); }
int cmd_checkout(git_repository *repo, int argc, char **argv) { int i, err, rc; char *branch; git_reference *branch_ref; git_checkout_options checkout_opts; branch = NULL; rc = EXIT_FAILURE; for (i=1;i<argc;i++) { if (argv[i][0] != '-') { if (!branch) branch = argv[i]; } else { } } if (!branch) { fprintf (stderr, "USAGE: %s <branch>\n", argv[0]); return -1; } /* Try local branch */ if (git_branch_lookup(&branch_ref,repo,branch,GIT_BRANCH_LOCAL) != 0) { /* No, try remote branch */ git_reference *remote_branch_ref; char remote_buf[256]; snprintf(remote_buf,sizeof(remote_buf),"%s/%s","origin",branch); if (git_branch_lookup(&remote_branch_ref, repo, remote_buf, GIT_BRANCH_REMOTE) == 0) { /* Exists, now try to create a local one from that reference */ if ((err = git2_create_branch_from_ref(&branch_ref,remote_branch_ref,repo,branch)) != 0) { fprintf(stderr,"Error code %d\n",err); libgit_error(); goto out; } git_reference_free(remote_branch_ref); } else { branch_ref = NULL; } } printf("Checking out %s\n",branch_ref?git_reference_name(branch_ref):branch); if ((err = git_repository_set_head(repo,branch_ref?git_reference_name(branch_ref):branch)) != 0) { fprintf(stderr,"Error code %d\n",err); libgit_error(); goto out; } /* Default options. Note by default we perform a dry checkout */ memset(&checkout_opts,0,sizeof(checkout_opts)); checkout_opts.version = GIT_CHECKOUT_OPTIONS_VERSION; checkout_opts.notify_cb = notify_cb; checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE|GIT_CHECKOUT_REMOVE_UNTRACKED;//GIT_CHECKOUT_SAFE|GIT_CHECKOUT_UPDATE_UNTRACKED; if (git_checkout_head(repo,&checkout_opts) != 0) { libgit_error(); goto out; } rc = EXIT_SUCCESS; out: if (branch_ref) git_reference_free(branch_ref); return rc; }
bool Masterlist::Update(const boost::filesystem::path& path, const std::string& repoUrl, const std::string& repoBranch) { GitHelper git; fs::path repoPath = path.parent_path(); string filename = path.filename().string(); if (repoUrl.empty() || repoBranch.empty()) throw std::invalid_argument("Repository URL and branch must not be empty."); // Initialise checkout options. BOOST_LOG_TRIVIAL(debug) << "Setting up checkout options."; char * paths = new char[filename.length() + 1]; strcpy(paths, filename.c_str()); git.GetData().checkout_options.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_DONT_REMOVE_EXISTING; git.GetData().checkout_options.paths.strings = &paths; git.GetData().checkout_options.paths.count = 1; // Initialise clone options. git.GetData().clone_options.checkout_opts = git.GetData().checkout_options; git.GetData().clone_options.bare = 0; git.GetData().clone_options.checkout_branch = repoBranch.c_str(); // Now try to access the repository if it exists, or clone one if it doesn't. BOOST_LOG_TRIVIAL(trace) << "Attempting to open the Git repository at: " << repoPath; if (!git.IsRepository(repoPath)) git.Clone(repoPath, repoUrl); else { // Repository exists: check settings are correct, then pull updates. git.SetErrorMessage((boost::format(translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); // Open the repository. BOOST_LOG_TRIVIAL(info) << "Existing repository found, attempting to open it."; git.Call(git_repository_open(&git.GetData().repo, repoPath.string().c_str())); // Set the remote URL. BOOST_LOG_TRIVIAL(info) << "Using remote URL: " << repoUrl; git.Call(git_remote_set_url(git.GetData().repo, "origin", repoUrl.c_str())); // Now fetch updates from the remote. git.Fetch("origin"); // Check that a local branch with the correct name exists. git.SetErrorMessage((boost::format(translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); int ret = git_branch_lookup(&git.GetData().reference, git.GetData().repo, repoBranch.c_str(), GIT_BRANCH_LOCAL); if (ret == GIT_ENOTFOUND) // Branch doesn't exist. Create a new branch using the remote branch's latest commit. git.CheckoutNewBranch("origin", repoBranch); else { // The local branch exists. Need to merge the remote branch // into it. git.Call(ret); // Handle other errors from preceding branch lookup. // Check if HEAD points to the desired branch and set it to if not. if (!git_branch_is_head(git.GetData().reference)) { BOOST_LOG_TRIVIAL(trace) << "Setting HEAD to follow branch: " << repoBranch; git.Call(git_repository_set_head(git.GetData().repo, (string("refs/heads/") + repoBranch).c_str())); } // Get remote branch reference. git.Call(git_branch_upstream(&git.GetData().reference2, git.GetData().reference)); BOOST_LOG_TRIVIAL(trace) << "Checking HEAD and remote branch's mergeability."; git_merge_analysis_t analysis; git_merge_preference_t pref; git.Call(git_annotated_commit_from_ref(&git.GetData().annotated_commit, git.GetData().repo, git.GetData().reference2)); git.Call(git_merge_analysis(&analysis, &pref, git.GetData().repo, (const git_annotated_commit **)&git.GetData().annotated_commit, 1)); if ((analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) == 0 && (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) == 0) { // The local branch can't be easily merged. Best just to delete and recreate it. BOOST_LOG_TRIVIAL(trace) << "Local branch cannot be easily merged with remote branch."; BOOST_LOG_TRIVIAL(trace) << "Deleting the local branch."; git.Call(git_branch_delete(git.GetData().reference)); // Need to free ref before calling git.CheckoutNewBranch() git_reference_free(git.GetData().reference); git.GetData().reference = nullptr; git_reference_free(git.GetData().reference2); git.GetData().reference2 = nullptr; git.CheckoutNewBranch("origin", repoBranch); } else { // Get remote branch commit ID. git.Call(git_reference_peel(&git.GetData().object, git.GetData().reference2, GIT_OBJ_COMMIT)); const git_oid * remote_commit_id = git_object_id(git.GetData().object); git_object_free(git.GetData().object); git.GetData().object = nullptr; git_reference_free(git.GetData().reference2); git.GetData().reference2 = nullptr; bool updateBranchHead = true; if ((analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) != 0) { // No merge is required, but HEAD might be ahead of the remote branch. Check // to see if that's the case, and move HEAD back to match the remote branch // if so. BOOST_LOG_TRIVIAL(trace) << "Local branch is up-to-date with remote branch."; BOOST_LOG_TRIVIAL(trace) << "Checking to see if local and remote branch heads are equal."; // Get local branch commit ID. git.Call(git_reference_peel(&git.GetData().object, git.GetData().reference, GIT_OBJ_COMMIT)); const git_oid * local_commit_id = git_object_id(git.GetData().object); git_object_free(git.GetData().object); git.GetData().object = nullptr; updateBranchHead = local_commit_id->id != remote_commit_id->id; // If the masterlist in // HEAD also matches the masterlist file, no further // action needs to be taken. Otherwise, a checkout // must be performed and the checked-out file parsed. if (!updateBranchHead) { BOOST_LOG_TRIVIAL(trace) << "Local and remote branch heads are equal."; if (!GitHelper::IsFileDifferent(repoPath, filename)) { BOOST_LOG_TRIVIAL(info) << "Local branch and masterlist file are already up to date."; return false; } } else BOOST_LOG_TRIVIAL(trace) << "Local branch heads is ahead of remote branch head."; } else BOOST_LOG_TRIVIAL(trace) << "Local branch can be fast-forwarded to remote branch."; if (updateBranchHead) { // The remote branch reference points to a particular // commit. Update the local branch reference to point // to the same commit. BOOST_LOG_TRIVIAL(trace) << "Syncing local branch head with remote branch head."; git.Call(git_reference_set_target(&git.GetData().reference2, git.GetData().reference, remote_commit_id, "Setting branch reference.")); git_reference_free(git.GetData().reference2); git.GetData().reference2 = nullptr; } git_reference_free(git.GetData().reference); git.GetData().reference = nullptr; BOOST_LOG_TRIVIAL(trace) << "Performing a Git checkout of HEAD."; git.Call(git_checkout_head(git.GetData().repo, &git.GetData().checkout_options)); } } } // Now whether the repository was cloned or updated, the working directory contains // the latest masterlist. Try parsing it: on failure, detach the HEAD back one commit // and try again. bool parsingFailed = false; std::string parsingError; git.SetErrorMessage((boost::format(translate("An error occurred while trying to read information on the updated masterlist. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); do { // Get the HEAD revision's short ID. string revision = git.GetHeadShortId(); //Now try parsing the masterlist. BOOST_LOG_TRIVIAL(debug) << "Testing masterlist parsing."; try { this->Load(path); parsingFailed = false; } catch (std::exception& e) { parsingFailed = true; if (parsingError.empty()) parsingError = boost::locale::translate("Masterlist revision").str() + " " + string(revision) + ": " + e.what() + ". " + boost::locale::translate("The latest masterlist revision contains a syntax error, LOOT is using the most recent valid revision instead. Syntax errors are usually minor and fixed within hours.").str(); //There was an error, roll back one revision. BOOST_LOG_TRIVIAL(error) << "Masterlist parsing failed. Masterlist revision " + string(revision) + ": " + e.what(); git.CheckoutRevision("HEAD^"); } } while (parsingFailed); if (!parsingError.empty()) AppendMessage(Message(MessageType::error, parsingError)); return true; }
void test_checkout_head__checking_out_an_orphaned_head_returns_GIT_EORPHANEDHEAD(void) { make_head_orphaned(g_repo, NON_EXISTING_HEAD); cl_assert_equal_i(GIT_EORPHANEDHEAD, git_checkout_head(g_repo, NULL)); }
static void checkout(git_repository *repo) { git_reference *master_ref, *remote_ref, *HEAD_ref, *tmpr; git_checkout_options co_opts; const char *remote_br_name; git_commit *remote_commit; git_object *remote_obj; char *remotebr; int rc; remotebr = NULL; xasprintf(&remotebr, "refs/remotes/%s/%s", option_origin, option_trunk); rc = git_reference_lookup(&remote_ref, repo, remotebr); if (rc) die("git_reference_lookup(%s): %d", remotebr, rc); rc = git_branch_name(&remote_br_name, remote_ref); if (rc) die("git_branch_name: %d", rc); rc = git_reference_peel(&remote_obj, remote_ref, GIT_OBJ_COMMIT); if (rc) die("git_reference_peel"); rc = git_commit_lookup(&remote_commit, repo, git_object_id(remote_obj)); if (rc) die("git_commit_lookup"); rc = git_branch_create(&master_ref, repo, "master", remote_commit, false, NULL, NULL); if (rc) die("git_branch_create: %d", rc); rc = git_reference_symbolic_create(&HEAD_ref, repo, "HEAD", "refs/heads/master", false, NULL, NULL); if (rc && rc != GIT_EEXISTS) die("git_reference_symbolic_create: %d", rc); rc = git_branch_set_upstream(master_ref, remote_br_name); if (rc) /* TODO: '' is not a valid remote name */ #if 0 die("git_branch_set_upstream: %d (%d/%s)", rc, giterr_last()->klass, giterr_last()->message); #else printf("XXXgit_branch_set_upstream: %d (%d/%s)\n", rc, giterr_last()->klass, giterr_last()->message); #endif rc = git_reference_lookup(&tmpr, repo, "refs/heads/master"); if (rc) die("%s: reference_lookup: master doesn't exist?", __func__); if (git_reference_cmp(tmpr, master_ref) != 0) die("mismatched master"); co_opts = (git_checkout_options) GIT_CHECKOUT_OPTIONS_INIT; co_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; rc = git_checkout_head(repo, &co_opts); if (rc) die("git_checkout_head"); free(remotebr); git_commit_free(remote_commit); git_object_free(remote_obj); git_reference_free(tmpr); git_reference_free(HEAD_ref); git_reference_free(master_ref); git_reference_free(remote_ref); }
void test_checkout_crlf__with_ident(void) { git_index *index; git_blob *blob; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_mkfile("crlf/.gitattributes", "*.txt text\n*.bin binary\n" "*.crlf text eol=crlf\n" "*.lf text eol=lf\n" "*.ident text ident\n" "*.identcrlf ident text eol=crlf\n" "*.identlf ident text eol=lf\n"); cl_repo_set_bool(g_repo, "core.autocrlf", true); /* add files with $Id$ */ cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW "\n$Id: initial content$\n"); cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW "\r\n$Id$\r\n\r\n"); cl_git_mkfile("crlf/more1.identlf", "$Id$\n" MORE_LF_TEXT_RAW); cl_git_mkfile("crlf/more2.identcrlf", "\r\n$Id: $\r\n" MORE_CRLF_TEXT_RAW); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_index_add_bypath(index, "lf.ident")); cl_git_pass(git_index_add_bypath(index, "crlf.ident")); cl_git_pass(git_index_add_bypath(index, "more1.identlf")); cl_git_pass(git_index_add_bypath(index, "more2.identcrlf")); cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Some ident files\n"); git_checkout_head(g_repo, &opts); /* check that blobs have $Id$ */ cl_git_pass(git_blob_lookup(&blob, g_repo, & git_index_get_bypath(index, "lf.ident", 0)->id)); cl_assert_equal_s( ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob)); git_blob_free(blob); cl_git_pass(git_blob_lookup(&blob, g_repo, & git_index_get_bypath(index, "more2.identcrlf", 0)->id)); cl_assert_equal_s( "\n$Id$\n" MORE_CRLF_TEXT_AS_LF, git_blob_rawcontent(blob)); git_blob_free(blob); /* check that filesystem is initially untouched - matching core Git */ cl_assert_equal_file( ALL_LF_TEXT_RAW "\n$Id: initial content$\n", 0, "crlf/lf.ident"); /* check that forced checkout rewrites correctly */ p_unlink("crlf/lf.ident"); p_unlink("crlf/crlf.ident"); p_unlink("crlf/more1.identlf"); p_unlink("crlf/more2.identcrlf"); git_checkout_head(g_repo, &opts); if (GIT_EOL_NATIVE == GIT_EOL_LF) { cl_assert_equal_file( ALL_LF_TEXT_RAW "\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467 $\n", 0, "crlf/lf.ident"); cl_assert_equal_file( ALL_CRLF_TEXT_AS_LF "\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857 $\n\n", 0, "crlf/crlf.ident"); } else { cl_assert_equal_file( ALL_LF_TEXT_AS_CRLF "\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467 $\r\n", 0, "crlf/lf.ident"); cl_assert_equal_file( ALL_CRLF_TEXT_RAW "\r\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857 $\r\n\r\n", 0, "crlf/crlf.ident"); } cl_assert_equal_file( "$Id: f7830382dac1f1583422be5530fdfbd26289431b $\n" MORE_LF_TEXT_AS_LF, 0, "crlf/more1.identlf"); cl_assert_equal_file( "\r\n$Id: 74677a68413012ce8d7e7cfc3f12603df3a3eac4 $\r\n" MORE_CRLF_TEXT_AS_CRLF, 0, "crlf/more2.identcrlf"); git_index_free(index); }