mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-10-26 05:40:14 +00:00 
			
		
		
		
	 331e7de900
			
		
	
	
		331e7de900
		
	
	
	
	
		
			
			* Rework GIT_DIRREMOVAL values to GIT_RMDIR flags, allowing combinations of flags * Add GIT_RMDIR_EMPTY_PARENTS flag to remove parent dirs that are left empty after removal * Add GIT_MKDIR_VERIFY_DIR to give an error if item is a file, not a dir (previously an EEXISTS error was ignored, even for files) and enable this flag for git_futils_mkpath2file call * Improve accuracy of error messages from git_futils_mkdir
		
			
				
	
	
		
			309 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "clar_libgit2.h"
 | |
| #include "posix.h"
 | |
| #include "path.h"
 | |
| #include "submodule_helpers.h"
 | |
| #include "fileops.h"
 | |
| 
 | |
| static git_repository *g_repo = NULL;
 | |
| 
 | |
| void test_submodule_status__initialize(void)
 | |
| {
 | |
| 	g_repo = cl_git_sandbox_init("submod2");
 | |
| 
 | |
| 	cl_fixture_sandbox("submod2_target");
 | |
| 	p_rename("submod2_target/.gitted", "submod2_target/.git");
 | |
| 
 | |
| 	/* must create submod2_target before rewrite so prettify will work */
 | |
| 	rewrite_gitmodules(git_repository_workdir(g_repo));
 | |
| 	p_rename("submod2/not_submodule/.gitted", "submod2/not_submodule/.git");
 | |
| }
 | |
| 
 | |
| void test_submodule_status__cleanup(void)
 | |
| {
 | |
| 	cl_git_sandbox_cleanup();
 | |
| 	cl_fixture_cleanup("submod2_target");
 | |
| }
 | |
| 
 | |
| void test_submodule_status__unchanged(void)
 | |
| {
 | |
| 	unsigned int status, expected;
 | |
| 	git_submodule *sm;
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	expected = GIT_SUBMODULE_STATUS_IN_HEAD |
 | |
| 		GIT_SUBMODULE_STATUS_IN_INDEX |
 | |
| 		GIT_SUBMODULE_STATUS_IN_CONFIG |
 | |
| 		GIT_SUBMODULE_STATUS_IN_WD;
 | |
| 
 | |
| 	cl_assert(status == expected);
 | |
| }
 | |
| 
 | |
| /* 4 values of GIT_SUBMODULE_IGNORE to check */
 | |
| 
 | |
| void test_submodule_status__ignore_none(void)
 | |
| {
 | |
| 	unsigned int status;
 | |
| 	git_submodule *sm;
 | |
| 	git_buf path = GIT_BUF_INIT;
 | |
| 
 | |
| 	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged"));
 | |
| 	cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
 | |
| 
 | |
| 	cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNTRACKED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0);
 | |
| 
 | |
| 	/* removed sm_unchanged for deleted workdir */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0);
 | |
| 
 | |
| 	/* now mkdir sm_unchanged to test uninitialized */
 | |
| 	cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0));
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_reload(sm));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0);
 | |
| 
 | |
| 	/* update sm_changed_head in index */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_add_to_index(sm, true));
 | |
| 	/* reload is not needed because add_to_index updates the submodule data */
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0);
 | |
| 
 | |
| 	/* remove sm_changed_head from index */
 | |
| 	{
 | |
| 		git_index *index;
 | |
| 		int pos;
 | |
| 
 | |
| 		cl_git_pass(git_repository_index(&index, g_repo));
 | |
| 		pos = git_index_find(index, "sm_changed_head");
 | |
| 		cl_assert(pos >= 0);
 | |
| 		cl_git_pass(git_index_remove(index, "sm_changed_head", 0));
 | |
| 		cl_git_pass(git_index_write(index));
 | |
| 
 | |
| 		git_index_free(index);
 | |
| 	}
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_reload(sm));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_DELETED) != 0);
 | |
| 
 | |
| 	git_buf_free(&path);
 | |
| }
 | |
| 
 | |
| static int set_sm_ignore(git_submodule *sm, const char *name, void *payload)
 | |
| {
 | |
| 	git_submodule_ignore_t ignore = *(git_submodule_ignore_t *)payload;
 | |
| 	GIT_UNUSED(name);
 | |
| 	git_submodule_set_ignore(sm, ignore);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void test_submodule_status__ignore_untracked(void)
 | |
| {
 | |
| 	unsigned int status;
 | |
| 	git_submodule *sm;
 | |
| 	git_buf path = GIT_BUF_INIT;
 | |
| 	git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_UNTRACKED;
 | |
| 
 | |
| 	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged"));
 | |
| 	cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign));
 | |
| 
 | |
| 	cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0);
 | |
| 
 | |
| 	/* removed sm_unchanged for deleted workdir */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0);
 | |
| 
 | |
| 	/* now mkdir sm_unchanged to test uninitialized */
 | |
| 	cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0));
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_reload(sm));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0);
 | |
| 
 | |
| 	/* update sm_changed_head in index */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_add_to_index(sm, true));
 | |
| 	/* reload is not needed because add_to_index updates the submodule data */
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0);
 | |
| 
 | |
| 	git_buf_free(&path);
 | |
| }
 | |
| 
 | |
| void test_submodule_status__ignore_dirty(void)
 | |
| {
 | |
| 	unsigned int status;
 | |
| 	git_submodule *sm;
 | |
| 	git_buf path = GIT_BUF_INIT;
 | |
| 	git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_DIRTY;
 | |
| 
 | |
| 	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged"));
 | |
| 	cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign));
 | |
| 
 | |
| 	cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0);
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0);
 | |
| 
 | |
| 	/* removed sm_unchanged for deleted workdir */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0);
 | |
| 
 | |
| 	/* now mkdir sm_unchanged to test uninitialized */
 | |
| 	cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0));
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_reload(sm));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0);
 | |
| 
 | |
| 	/* update sm_changed_head in index */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_add_to_index(sm, true));
 | |
| 	/* reload is not needed because add_to_index updates the submodule data */
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0);
 | |
| 
 | |
| 	git_buf_free(&path);
 | |
| }
 | |
| 
 | |
| void test_submodule_status__ignore_all(void)
 | |
| {
 | |
| 	unsigned int status;
 | |
| 	git_submodule *sm;
 | |
| 	git_buf path = GIT_BUF_INIT;
 | |
| 	git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_ALL;
 | |
| 
 | |
| 	cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged"));
 | |
| 	cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign));
 | |
| 
 | |
| 	cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	/* removed sm_unchanged for deleted workdir */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	/* now mkdir sm_unchanged to test uninitialized */
 | |
| 	cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0));
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
 | |
| 	cl_git_pass(git_submodule_reload(sm));
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	/* update sm_changed_head in index */
 | |
| 	cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
 | |
| 	cl_git_pass(git_submodule_add_to_index(sm, true));
 | |
| 	/* reload is not needed because add_to_index updates the submodule data */
 | |
| 	cl_git_pass(git_submodule_status(&status, sm));
 | |
| 	cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status));
 | |
| 
 | |
| 	git_buf_free(&path);
 | |
| }
 |