filemodes.c 5.02 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#include "clar_libgit2.h"
#include "buffer.h"
#include "posix.h"
#include "index.h"

static git_repository *g_repo = NULL;

void test_index_filemodes__initialize(void)
{
	g_repo = cl_git_sandbox_init("filemodes");
}

void test_index_filemodes__cleanup(void)
{
	cl_git_sandbox_cleanup();
}

void test_index_filemodes__read(void)
{
	git_index *index;
	unsigned int i;
	static bool expected[6] = { 0, 1, 0, 1, 0, 1 };

	cl_git_pass(git_repository_index(&index, g_repo));
25
	cl_assert_equal_i(6, (int)git_index_entrycount(index));
26 27

	for (i = 0; i < 6; ++i) {
Ben Straub committed
28
		const git_index_entry *entry = git_index_get_byindex(index, i);
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
		cl_assert(entry != NULL);
		cl_assert(((entry->mode & 0100) ? 1 : 0) == expected[i]);
	}

	git_index_free(index);
}

static void replace_file_with_mode(
	const char *filename, const char *backup, unsigned int create_mode)
{
	git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;

	cl_git_pass(git_buf_joinpath(&path, "filemodes", filename));
	cl_git_pass(git_buf_printf(&content, "%s as %08u (%d)",
		filename, create_mode, rand()));

	cl_git_pass(p_rename(path.ptr, backup));
	cl_git_write2file(
47 48
		path.ptr, content.ptr, content.size,
		O_WRONLY|O_CREAT|O_TRUNC, create_mode);
49 50 51 52 53

	git_buf_free(&path);
	git_buf_free(&content);
}

54 55 56 57 58
#define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__)

static void add_and_check_mode_(
	git_index *index, const char *filename, unsigned int expect_mode,
	const char *file, int line)
59
{
60
	size_t pos;
Ben Straub committed
61
	const git_index_entry *entry;
62

63
	cl_git_pass(git_index_add_bypath(index, filename));
64

65 66
	clar__assert(!git_index_find(&pos, index, filename),
		file, line, "Cannot find index entry", NULL, 1);
67

Edward Thomson committed
68
	entry = git_index_get_byindex(index, pos);
69 70 71

	clar__assert_equal(file, line, "Expected mode does not match index",
		1, "%07o", (unsigned int)entry->mode, (unsigned int)expect_mode);
72 73 74 75 76 77
}

void test_index_filemodes__untrusted(void)
{
	git_index *index;

78
	cl_repo_set_bool(g_repo, "core.filemode", false);
79 80 81 82 83 84

	cl_git_pass(git_repository_index(&index, g_repo));
	cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) != 0);

	/* 1 - add 0644 over existing 0644 -> expect 0644 */
	replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
nulltoken committed
85
	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB);
86 87 88

	/* 2 - add 0644 over existing 0755 -> expect 0755 */
	replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
nulltoken committed
89
	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE);
90 91 92

	/* 3 - add 0755 over existing 0644 -> expect 0644 */
	replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
nulltoken committed
93
	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB);
94 95 96

	/* 4 - add 0755 over existing 0755 -> expect 0755 */
	replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
nulltoken committed
97
	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE);
98

99 100 101 102 103 104 105 106 107
	/*  5 - add new 0644 -> expect 0644 */
	cl_git_write2file("filemodes/new_off", "blah", 0,
		O_WRONLY | O_CREAT | O_TRUNC, 0644);
	add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB);

	/* 6 - add new 0755 -> expect 0644 if core.filemode == false */
	cl_git_write2file("filemodes/new_on", "blah", 0,
		O_WRONLY | O_CREAT | O_TRUNC, 0755);
	add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB);
108 109 110 111 112 113 114 115 116 117 118 119 120 121

	git_index_free(index);
}

void test_index_filemodes__trusted(void)
{
	git_index *index;

	/* Only run these tests on platforms where I can actually
	 * chmod a file and get the stat results I expect!
	 */
	if (!cl_is_chmod_supported())
		return;

122
	cl_repo_set_bool(g_repo, "core.filemode", true);
123 124 125 126 127 128

	cl_git_pass(git_repository_index(&index, g_repo));
	cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) == 0);

	/* 1 - add 0644 over existing 0644 -> expect 0644 */
	replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644);
nulltoken committed
129
	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB);
130 131 132

	/* 2 - add 0644 over existing 0755 -> expect 0644 */
	replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644);
nulltoken committed
133
	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB);
134 135 136

	/* 3 - add 0755 over existing 0644 -> expect 0755 */
	replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755);
nulltoken committed
137
	add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE);
138 139 140

	/* 4 - add 0755 over existing 0755 -> expect 0755 */
	replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755);
nulltoken committed
141
	add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE);
142

Edward Thomson committed
143
	/*  5 - add new 0644 -> expect 0644 */
144
	cl_git_write2file("filemodes/new_off", "blah", 0,
145
		O_WRONLY | O_CREAT | O_TRUNC, 0644);
nulltoken committed
146
	add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB);
147

Edward Thomson committed
148
	/* 6 - add 0755 -> expect 0755 */
149
	cl_git_write2file("filemodes/new_on", "blah", 0,
150
		O_WRONLY | O_CREAT | O_TRUNC, 0755);
nulltoken committed
151
	add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE);
152 153 154

	git_index_free(index);
}
155 156 157 158 159 160 161 162 163 164 165 166 167 168

void test_index_filemodes__invalid(void)
{
	git_index *index;
	git_index_entry entry;

	cl_git_pass(git_repository_index(&index, g_repo));

	entry.path = "foo";
	entry.mode = GIT_OBJ_BLOB;
	cl_git_fail(git_index_add(index, &entry));

	entry.mode = GIT_FILEMODE_BLOB;
	cl_git_pass(git_index_add(index, &entry));
169 170

	git_index_free(index);
171
}