void test_submodule_lookup__accessors(void) { git_submodule *sm; const char *oid = "480095882d281ed676fe5b863569520e54a7d5c0"; cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); cl_assert(git_submodule_owner(sm) == g_repo); cl_assert_equal_s("sm_unchanged", git_submodule_name(sm)); cl_assert(git__suffixcmp(git_submodule_path(sm), "sm_unchanged") == 0); cl_assert(git__suffixcmp(git_submodule_url(sm), "/submod2_target") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE); cl_assert(git_submodule_update(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT); git_submodule_free(sm); cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); cl_assert_equal_s("sm_changed_head", git_submodule_name(sm)); cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "3d9386c507f6b093471a3e324085657a3c2b4247") == 0); git_submodule_free(sm); cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); cl_assert_equal_s("sm_added_and_uncommited", git_submodule_name(sm)); cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); cl_assert(git_submodule_head_id(sm) == NULL); cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); git_submodule_free(sm); cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); cl_assert_equal_s("sm_missing_commits", git_submodule_name(sm)); cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "5e4963595a9774b90524d35a807169049de8ccad") == 0); git_submodule_free(sm); }
void test_submodule_update__update_and_init_submodule(void) { git_submodule *sm; git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT; unsigned int submodule_status = 0; g_repo = setup_fixture_submodule_simple(); /* get the submodule */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_WD_UNINITIALIZED); /* update (with option to initialize sub repo) */ cl_git_pass(git_submodule_update(sm, 1, &update_options)); /* verify expected state */ cl_assert(git_oid_streq(git_submodule_head_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); git_submodule_free(sm); }
static int checksum_submodule (struct TreeWalkData *parent_twdata, git_submodule *sub) { int r = 1; const git_oid *sub_head; struct TreeWalkData child_twdata = { FALSE, parent_twdata->evtag, NULL, NULL, parent_twdata->cancellable, parent_twdata->error }; parent_twdata->evtag->n_submodules++; r = git_submodule_open (&child_twdata.repo, sub); if (!handle_libgit_ret (r, child_twdata.error)) goto out; r = git_repository_odb (&child_twdata.odb, child_twdata.repo); if (!handle_libgit_ret (r, child_twdata.error)) goto out; sub_head = git_submodule_wd_id (sub); if (!checksum_commit_contents (&child_twdata, sub_head, child_twdata.cancellable, child_twdata.error)) goto out; r = 0; out: if (r > 0) child_twdata.caught_error = TRUE; if (child_twdata.repo) git_repository_free (child_twdata.repo); if (child_twdata.odb) git_odb_free (child_twdata.odb); return r; }
static bool checkout_is_workdir_modified( checkout_data *data, const git_diff_file *baseitem, const git_index_entry *wditem) { git_oid oid; const git_index_entry *ie; /* handle "modified" submodule */ if (wditem->mode == GIT_FILEMODE_COMMIT) { git_submodule *sm; unsigned int sm_status = 0; const git_oid *sm_oid = NULL; if (git_submodule_lookup(&sm, data->repo, wditem->path) < 0 || git_submodule_status(&sm_status, sm) < 0) return true; if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) return true; sm_oid = git_submodule_wd_id(sm); if (!sm_oid) return false; return (git_oid__cmp(&baseitem->oid, sm_oid) != 0); } /* Look at the cache to decide if the workdir is modified. If not, * we can simply compare the oid in the cache to the baseitem instead * of hashing the file. */ if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) { if (wditem->mtime.seconds == ie->mtime.seconds && wditem->mtime.nanoseconds == ie->mtime.nanoseconds && wditem->file_size == ie->file_size) return (git_oid__cmp(&baseitem->oid, &ie->oid) != 0); } /* depending on where base is coming from, we may or may not know * the actual size of the data, so we can't rely on this shortcut. */ if (baseitem->size && wditem->file_size != baseitem->size) return true; if (git_diff__oid_for_file( data->repo, wditem->path, wditem->mode, wditem->file_size, &oid) < 0) return false; return (git_oid__cmp(&baseitem->oid, &oid) != 0); }
static int diff_file_content_commit_to_str( git_diff_file_content *fc, bool check_status) { char oid[GIT_OID_HEXSZ+1]; git_buf content = GIT_BUF_INIT; const char *status = ""; if (check_status) { int error = 0; git_submodule *sm = NULL; unsigned int sm_status = 0; const git_oid *sm_head; if ((error = git_submodule_lookup(&sm, fc->repo, fc->file->path)) < 0) { /* GIT_EEXISTS means a "submodule" that has not been git added */ if (error == GIT_EEXISTS) { giterr_clear(); error = 0; } return error; } if ((error = git_submodule_status(&sm_status, fc->repo, fc->file->path, GIT_SUBMODULE_IGNORE_UNSPECIFIED)) < 0) { git_submodule_free(sm); return error; } /* update OID if we didn't have it previously */ if ((fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0 && ((sm_head = git_submodule_wd_id(sm)) != NULL || (sm_head = git_submodule_head_id(sm)) != NULL)) { git_oid_cpy(&fc->file->id, sm_head); fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; } if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) status = "-dirty"; git_submodule_free(sm); } git_oid_tostr(oid, sizeof(oid), &fc->file->id); if (git_buf_printf(&content, "Subproject commit %s%s\n", oid, status) < 0) return -1; fc->map.len = git_buf_len(&content); fc->map.data = git_buf_detach(&content); fc->flags |= GIT_DIFF_FLAG__FREE_DATA; return 0; }
void test_submodule_update__update_submodule(void) { git_submodule *sm; git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT; unsigned int submodule_status = 0; struct update_submodule_cb_payload update_payload = { 0 }; g_repo = setup_fixture_submodule_simple(); update_options.checkout_opts.progress_cb = checkout_progress_cb; update_options.checkout_opts.progress_payload = &update_payload; update_options.remote_callbacks.update_tips = update_tips; update_options.remote_callbacks.payload = &update_payload; /* get the submodule */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); /* verify the initial state of the submodule */ cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_WD_UNINITIALIZED); /* initialize and update the submodule */ cl_git_pass(git_submodule_init(sm, 0)); cl_git_pass(git_submodule_update(sm, 0, &update_options)); /* verify state */ cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD); cl_assert(git_oid_streq(git_submodule_head_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); /* verify that the expected callbacks have been called. */ cl_assert_equal_i(1, update_payload.checkout_progress_called); cl_assert_equal_i(1, update_payload.update_tips_called); git_submodule_free(sm); }
void test_submodule_update__can_force_update(void) { git_submodule *sm = NULL; git_checkout_options checkout_options = GIT_CHECKOUT_OPTIONS_INIT; git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT; unsigned int submodule_status = 0; git_reference *branch_reference = NULL; git_object *branch_commit = NULL; g_repo = setup_fixture_submodule_simple(); /* Initialize and update the sub repository */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_WD_UNINITIALIZED); cl_git_pass(git_submodule_update(sm, 1, &update_options)); /* verify expected state */ cl_assert(git_oid_streq(git_submodule_head_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); /* checkout the alternate_1 branch */ checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE; cl_git_pass(git_reference_lookup(&branch_reference, g_repo, "refs/heads/alternate_1")); cl_git_pass(git_reference_peel(&branch_commit, branch_reference, GIT_OBJ_COMMIT)); cl_git_pass(git_checkout_tree(g_repo, branch_commit, &checkout_options)); cl_git_pass(git_repository_set_head(g_repo, git_reference_name(branch_reference))); /* * Verify state after checkout of parent repository. The submodule ID in the * HEAD commit and index should be updated, but not the workdir. */ cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS_WD_MODIFIED); cl_assert(git_oid_streq(git_submodule_head_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); /* * Create a conflicting edit in the subrepository to verify that * the submodule update action is blocked. */ cl_git_write2file("submodule_simple/testrepo/branch_file.txt", "a conflicting edit", 0, O_WRONLY | O_CREAT | O_TRUNC, 0777); /* forcefully checkout and verify the submodule state was updated. */ update_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_submodule_update(sm, 0, &update_options)); cl_assert(git_oid_streq(git_submodule_head_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); git_submodule_free(sm); git_object_free(branch_commit); git_reference_free(branch_reference); }
void test_submodule_update__update_already_checked_out_submodule(void) { git_submodule *sm = NULL; git_checkout_options checkout_options = GIT_CHECKOUT_OPTIONS_INIT; git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT; unsigned int submodule_status = 0; git_reference *branch_reference = NULL; git_object *branch_commit = NULL; struct update_submodule_cb_payload update_payload = { 0 }; g_repo = setup_fixture_submodule_simple(); update_options.checkout_opts.progress_cb = checkout_progress_cb; update_options.checkout_opts.progress_payload = &update_payload; /* Initialize and update the sub repository */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_WD_UNINITIALIZED); cl_git_pass(git_submodule_update(sm, 1, &update_options)); /* verify expected state */ cl_assert(git_oid_streq(git_submodule_head_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); /* checkout the alternate_1 branch */ checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE; cl_git_pass(git_reference_lookup(&branch_reference, g_repo, "refs/heads/alternate_1")); cl_git_pass(git_reference_peel(&branch_commit, branch_reference, GIT_OBJ_COMMIT)); cl_git_pass(git_checkout_tree(g_repo, branch_commit, &checkout_options)); cl_git_pass(git_repository_set_head(g_repo, git_reference_name(branch_reference))); /* * Verify state after checkout of parent repository. The submodule ID in the * HEAD commit and index should be updated, but not the workdir. */ cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS_WD_MODIFIED); cl_assert(git_oid_streq(git_submodule_head_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); /* * Update the submodule and verify the state. * Now, the HEAD, index, and Workdir commits should all be updated to * the new commit. */ cl_git_pass(git_submodule_update(sm, 0, &update_options)); cl_assert(git_oid_streq(git_submodule_head_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); /* verify that the expected callbacks have been called. */ cl_assert_equal_i(1, update_payload.checkout_progress_called); git_submodule_free(sm); git_object_free(branch_commit); git_reference_free(branch_reference); }