Пример #1
0
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
{
	git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;

	set_repo_symlink_handling_cap_to(true);

	opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;

	cl_git_pass(git_checkout_index(g_repo, NULL, &opts));

#ifdef GIT_WIN32
	test_file_contents("./testrepo/link_to_new.txt", "new.txt");
#else
	{
		char link_data[1024];
		size_t link_size = 1024;

		link_size = p_readlink("./testrepo/link_to_new.txt", link_data, link_size);
		link_data[link_size] = '\0';
		cl_assert_equal_i(link_size, strlen("new.txt"));
		cl_assert_equal_s(link_data, "new.txt");
		test_file_contents("./testrepo/link_to_new.txt", "my new file\n");
	}
#endif
}
Пример #2
0
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
{
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;

	cl_repo_set_bool(g_repo, "core.symlinks", true);

	opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING;

	cl_git_pass(git_checkout_index(g_repo, NULL, &opts));

#ifdef GIT_WIN32
	check_file_contents("./testrepo/link_to_new.txt", "new.txt");
#else
	{
		char link_data[1024];
		size_t link_size = 1024;

		link_size = p_readlink("./testrepo/link_to_new.txt", link_data, link_size);
		link_data[link_size] = '\0';
		cl_assert_equal_i(link_size, strlen("new.txt"));
		cl_assert_equal_s(link_data, "new.txt");
		check_file_contents("./testrepo/link_to_new.txt", "my new file\n");
	}
#endif
}
Пример #3
0
static int diff_file_content_load_workdir_symlink(
	git_diff_file_content *fc, git_buf *path)
{
	ssize_t alloc_len, read_len;
	int symlink_supported, error;

	if ((error = git_repository__cvar(
		&symlink_supported, fc->repo, GIT_CVAR_SYMLINKS)) < 0)
		return -1;

	if (!symlink_supported)
		return diff_file_content_load_workdir_symlink_fake(fc, path);

	/* link path on disk could be UTF-16, so prepare a buffer that is
	 * big enough to handle some UTF-8 data expansion
	 */
	alloc_len = (ssize_t)(fc->file->size * 2) + 1;

	fc->map.data = git__calloc(alloc_len, sizeof(char));
	GITERR_CHECK_ALLOC(fc->map.data);

	fc->flags |= GIT_DIFF_FLAG__FREE_DATA;

	read_len = p_readlink(git_buf_cstr(path), fc->map.data, alloc_len);
	if (read_len < 0) {
		giterr_set(GITERR_OS, "failed to read symlink '%s'", fc->file->path);
		return -1;
	}

	fc->map.len = read_len;
	return 0;
}
Пример #4
0
void test_checkout_index__honor_coresymlinks_default(void)
{
	git_repository *repo;
	git_remote *origin;
	git_object *target;
	char cwd[GIT_PATH_MAX];

	const char *url = git_repository_path(g_repo);

	cl_assert(getcwd(cwd, sizeof(cwd)) != NULL);
	cl_assert_equal_i(0, p_mkdir("readonly", 0555)); // Read-only directory
	cl_assert_equal_i(0, chdir("readonly"));
	cl_git_pass(git_repository_init(&repo, "../symlink.git", true));
	cl_assert_equal_i(0, chdir(cwd));
	cl_assert_equal_i(0, p_mkdir("symlink", 0777));
	cl_git_pass(git_repository_set_workdir(repo, "symlink", 1));

	cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url));
	cl_git_pass(git_remote_fetch(origin, NULL, NULL, NULL));
	git_remote_free(origin);

	cl_git_pass(git_revparse_single(&target, repo, "remotes/origin/master"));
	cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL));
	git_object_free(target);
	git_repository_free(repo);

#ifdef GIT_WIN32
	check_file_contents("./symlink/link_to_new.txt", "new.txt");
#else
	{
		char link_data[1024];
		size_t link_size = 1024;

		link_size = p_readlink("./symlink/link_to_new.txt", link_data, link_size);
		link_data[link_size] = '\0';
		cl_assert_equal_i(link_size, strlen("new.txt"));
		cl_assert_equal_s(link_data, "new.txt");
		check_file_contents("./symlink/link_to_new.txt", "my new file\n");
	}
#endif

	cl_fixture_cleanup("symlink");
}
Пример #5
0
int git_odb__hashlink(git_oid *out, const char *path)
{
	struct stat st;
	git_off_t size;
	int result;

	if (git_path_lstat(path, &st) < 0)
		return -1;

	size = st.st_size;

	if (!git__is_sizet(size)) {
		giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
		return -1;
	}

	if (S_ISLNK(st.st_mode)) {
		char *link_data;
		ssize_t read_len;

		link_data = (char*) git__malloc((size_t)(size + 1));
		GITERR_CHECK_ALLOC(link_data);

		read_len = p_readlink(path, link_data, (size_t)size);
		link_data[size] = '\0';
		if (read_len != (ssize_t)size) {
			giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path);
			git__free(link_data);
			return -1;
		}

		result = git_odb_hash(out, link_data, (size_t)size, GIT_OBJ_BLOB);
		git__free(link_data);
	} else {
		int fd = git_futils_open_ro(path);
		if (fd < 0)
			return -1;
		result = git_odb__hashfd(out, fd, (size_t)size, GIT_OBJ_BLOB);
		p_close(fd);
	}

	return result;
}
Пример #6
0
static int write_symlink(
	git_oid *id, git_odb *odb, const char *path, size_t link_size)
{
	char *link_data;
	ssize_t read_len;
	int error;

	link_data = git__malloc(link_size);
	GITERR_CHECK_ALLOC(link_data);

	read_len = p_readlink(path, link_data, link_size);
	if (read_len != (ssize_t)link_size) {
		giterr_set(GITERR_OS, "failed to create blob: cannot read symlink '%s'", path);
		git__free(link_data);
		return -1;
	}

	error = git_odb_write(id, odb, (void *)link_data, link_size, GIT_OBJECT_BLOB);
	git__free(link_data);
	return error;
}
Пример #7
0
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
{
	set_repo_symlink_handling_cap_to(true);

	cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL));

#ifdef GIT_WIN32
	test_file_contents("./testrepo/link_to_new.txt", "new.txt");
#else
	{
		char link_data[1024];
		size_t link_size = 1024;

		link_size = p_readlink("./testrepo/link_to_new.txt", link_data, link_size);
		link_data[link_size] = '\0';
		cl_assert_equal_i(link_size, strlen("new.txt"));
		cl_assert_equal_s(link_data, "new.txt");
		test_file_contents("./testrepo/link_to_new.txt", "my new file\n");
	}
#endif
}
Пример #8
0
static void ensure_workdir_link(const char *path, const char *target)
{
#ifdef GIT_WIN32
	ensure_workdir_contents(path, target);
#else
	git_buf fullpath = GIT_BUF_INIT;
	char actual[1024];
	struct stat st;
	int len;

	cl_git_pass(
		git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path));

	cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st));
	cl_assert(S_ISLNK(st.st_mode));

	cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0);
	actual[len] = '\0';
	cl_assert(strcmp(actual, target) == 0);

	git_buf_free(&fullpath);
#endif
}
Пример #9
0
static int do_lstat(
	const char *file_name, struct stat *buf, int posix_enotdir)
{
	WIN32_FILE_ATTRIBUTE_DATA fdata;
	wchar_t fbuf[GIT_WIN_PATH], lastch;
	int flen;

	flen = git__utf8_to_16(fbuf, GIT_WIN_PATH, file_name);

	/* truncate trailing slashes */
	for (; flen > 0; --flen) {
		lastch = fbuf[flen - 1];
		if (WIN32_IS_WSEP(lastch))
			fbuf[flen - 1] = L'\0';
		else if (lastch != L'\0')
			break;
	}

	if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
		int fMode = S_IREAD;

		if (!buf)
			return 0;

		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			fMode |= S_IFDIR;
		else
			fMode |= S_IFREG;

		if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
			fMode |= S_IWRITE;

		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
			fMode |= S_IFLNK;

		buf->st_ino = 0;
		buf->st_gid = 0;
		buf->st_uid = 0;
		buf->st_nlink = 1;
		buf->st_mode = (mode_t)fMode;
		buf->st_size = ((git_off_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow;
		buf->st_dev = buf->st_rdev = (_getdrive() - 1);
		buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
		buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
		buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));

		/* Windows symlinks have zero file size, call readlink to determine
		 * the length of the path pointed to, which we expect everywhere else
		 */
		if (S_ISLNK(fMode)) {
			char target[GIT_WIN_PATH];
			int readlink_result;

			readlink_result = p_readlink(file_name, target, GIT_WIN_PATH);

			if (readlink_result == -1)
				return -1;

			buf->st_size = strlen(target);
		}

		return 0;
	}

	errno = ENOENT;

	/* We need POSIX behavior, then ENOTDIR must set when any of the folders in the
	 * file path is a regular file,otherwise ENOENT must be set.
	 */
	if (posix_enotdir) {
		/* scan up path until we find an existing item */
		while (1) {
			/* remove last directory component */
			for (--flen; flen > 0 && !WIN32_IS_WSEP(fbuf[flen]); --flen);

			if (flen <= 0)
				break;

			fbuf[flen] = L'\0';

			if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
				if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
					errno = ENOTDIR;
				break;
			}
		}
	}

	return -1;
}