Esempio n. 1
0
File: soft.c Progetto: 0CV0/libgit2
void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE_HEAD_file_existence(void)
{
	git_index *index;
	git_reference *head;
	git_buf merge_head_path = GIT_BUF_INIT;

	cl_git_sandbox_cleanup();

	repo = cl_git_sandbox_init("mergedrepo");

	cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD"));
	cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path)));
	git_buf_free(&merge_head_path);

	cl_git_pass(git_repository_index(&index, repo));
	cl_assert_equal_i(true, git_index_has_conflicts(index));
	git_index_free(index);

	cl_git_pass(git_repository_head(&head, repo));
	cl_git_pass(git_reference_peel(&target, head, GIT_OBJ_COMMIT));
	git_reference_free(head);

	cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT));
}
Esempio n. 2
0
int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len)
{
	size_t actual_len = 0, i;
	git_oid actual_oid, expected_oid;
	git_buf wd = GIT_BUF_INIT;

	git_buf_puts(&wd, repo->workdir);
	git_path_direach(&wd, 0, dircount, &actual_len);

	if (actual_len != expected_len)
		return 0;

	for (i = 0; i < expected_len; i++) {
		git_blob_create_fromworkdir(&actual_oid, repo, expected[i].path);
		git_oid_fromstr(&expected_oid, expected[i].oid_str);

		if (git_oid_cmp(&actual_oid, &expected_oid) != 0)
			return 0;
	}

	git_buf_free(&wd);

	return 1;
}
Esempio n. 3
0
File: crlf.c Progetto: 1336/libgit2
void test_filter_crlf__to_odb(void)
{
	git_filter_list *fl;
	git_filter *crlf;
	git_buf in = { 0 }, out = { 0 };

	cl_git_pass(git_filter_list_new(
		&fl, g_repo, GIT_FILTER_TO_ODB, 0));

	crlf = git_filter_lookup(GIT_FILTER_CRLF);
	cl_assert(crlf != NULL);

	cl_git_pass(git_filter_list_push(fl, crlf, NULL));

	in.ptr = "Some text\r\nRight here\r\n";
	in.size = strlen(in.ptr);

	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));

	cl_assert_equal_s("Some text\nRight here\n", out.ptr);

	git_filter_list_free(fl);
	git_buf_free(&out);
}
Esempio n. 4
0
File: init.c Progetto: Arhzi/libgit2
void test_repo_init__external_templates_specified_in_config(void)
{
	git_buf template_path = GIT_BUF_INIT;

	git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;

	cl_set_cleanup(&cleanup_repository, "templated.git");
	template_sandbox("template");

	cl_git_pass(git_buf_joinpath(&template_path, clar_sandbox_path(),
		"template"));

	configure_templatedir(template_path.ptr);

	opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
		GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;

	cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts));

	validate_templates(_repo, "template");
	cl_fixture_cleanup("template");

	git_buf_free(&template_path);
}
Esempio n. 5
0
void test_refs_reflog_messages__creating_branches_default_messages(void)
{
	git_buf buf = GIT_BUF_INIT;
	git_annotated_commit *annotated;
	git_object *obj;
	git_commit *target;
	git_reference *branch1, *branch2;

	cl_git_pass(git_revparse_single(&obj, g_repo, "e90810b8df3"));
	cl_git_pass(git_commit_lookup(&target, g_repo, git_object_id(obj)));
	git_object_free(obj);

	cl_git_pass(git_branch_create(&branch1, g_repo, NEW_BRANCH_NAME, target, false));

	cl_git_pass(git_buf_printf(&buf, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target))));
	cl_reflog_check_entry(g_repo, "refs/heads/" NEW_BRANCH_NAME, 0,
		GIT_OID_HEX_ZERO,
		git_oid_tostr_s(git_commit_id(target)),
		g_email, git_buf_cstr(&buf));

	cl_git_pass(git_reference_remove(g_repo, "refs/heads/" NEW_BRANCH_NAME));

	cl_git_pass(git_annotated_commit_from_revspec(&annotated, g_repo, "e90810b8df3"));
	cl_git_pass(git_branch_create_from_annotated(&branch2, g_repo, NEW_BRANCH_NAME, annotated, true));

	cl_reflog_check_entry(g_repo, "refs/heads/" NEW_BRANCH_NAME, 0,
		GIT_OID_HEX_ZERO,
		git_oid_tostr_s(git_commit_id(target)),
		g_email, "branch: Created from e90810b8df3");

	git_annotated_commit_free(annotated);
	git_buf_free(&buf);
	git_commit_free(target);
	git_reference_free(branch1);
	git_reference_free(branch2);
}
Esempio n. 6
0
void test_object_shortid__select(void)
{
	git_oid full;
	git_object *obj;
	git_buf shorty = {0};

	git_oid_fromstr(&full, "ce013625030ba8dba906f756967f9e9ca394464a");
	cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
	cl_git_pass(git_object_short_id(&shorty, obj));
	cl_assert_equal_i(7, shorty.size);
	cl_assert_equal_s("ce01362", shorty.ptr);
	git_object_free(obj);

	git_oid_fromstr(&full, "038d718da6a1ebbc6a7780a96ed75a70cc2ad6e2");
	cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
	cl_git_pass(git_object_short_id(&shorty, obj));
	cl_assert_equal_i(7, shorty.size);
	cl_assert_equal_s("038d718", shorty.ptr);
	git_object_free(obj);

	git_oid_fromstr(&full, "dea509d097ce692e167dfc6a48a7a280cc5e877e");
	cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
	cl_git_pass(git_object_short_id(&shorty, obj));
	cl_assert_equal_i(9, shorty.size);
	cl_assert_equal_s("dea509d09", shorty.ptr);
	git_object_free(obj);

	git_oid_fromstr(&full, "dea509d0b3cb8ee0650f6ca210bc83f4678851ba");
	cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
	cl_git_pass(git_object_short_id(&shorty, obj));
	cl_assert_equal_i(9, shorty.size);
	cl_assert_equal_s("dea509d0b", shorty.ptr);
	git_object_free(obj);

	git_buf_free(&shorty);
}
Esempio n. 7
0
static int win32_find_existing_dirs(
	git_buf *out, const wchar_t *tmpl[])
{
	_findfile_path path16;
	git_buf buf = GIT_BUF_INIT;

	git_buf_clear(out);

	for (; *tmpl != NULL; tmpl++) {
		if (!git_win32__expand_path(&path16, *tmpl) &&
			path16.path[0] != L'%' &&
			!_waccess(path16.path, F_OK))
		{
			win32_path_to_8(&buf, path16.path);

			if (buf.size)
				git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
		}
	}

	git_buf_free(&buf);

	return (git_buf_oom(out) ? -1 : 0);
}
Esempio n. 8
0
int git_futils_dirs_set(git_futils_dir_t which, const char *search_path)
{
	const char *expand_path = NULL;
	git_buf merge = GIT_BUF_INIT;

	GITERR_CHECK_ERROR(git_futils_check_selector(which));

	if (search_path != NULL)
		expand_path = strstr(search_path, PATH_MAGIC);

	/* init with default if not yet done and needed (ignoring error) */
	if ((!search_path || expand_path) &&
		!git_buf_len(&git_futils__dirs[which]))
		git_futils__dir_guess[which](&git_futils__dirs[which]);

	/* if $PATH is not referenced, then just set the path */
	if (!expand_path)
		return git_buf_sets(&git_futils__dirs[which], search_path);

	/* otherwise set to join(before $PATH, old value, after $PATH) */
	if (expand_path > search_path)
		git_buf_set(&merge, search_path, expand_path - search_path);

	if (git_buf_len(&git_futils__dirs[which]))
		git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR,
			merge.ptr, git_futils__dirs[which].ptr);

	expand_path += strlen(PATH_MAGIC);
	if (*expand_path)
		git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);

	git_buf_swap(&git_futils__dirs[which], &merge);
	git_buf_free(&merge);

	return git_buf_oom(&git_futils__dirs[which]) ? -1 : 0;
}
Esempio n. 9
0
void test_core_buffer__base64(void)
{
	git_buf buf = GIT_BUF_INIT;

	/*     t  h  i  s
	 * 0x 74 68 69 73
     * 0b 01110100 01101000 01101001 01110011
	 * 0b 011101 000110 100001 101001 011100 110000
	 * 0x 1d 06 21 29 1c 30
	 *     d  G  h  p  c  w
	 */
	cl_git_pass(git_buf_put_base64(&buf, "this", 4));
	cl_assert_equal_s("dGhpcw==", buf.ptr);

	git_buf_clear(&buf);
	cl_git_pass(git_buf_put_base64(&buf, "this!", 5));
	cl_assert_equal_s("dGhpcyE=", buf.ptr);

	git_buf_clear(&buf);
	cl_git_pass(git_buf_put_base64(&buf, "this!\n", 6));
	cl_assert_equal_s("dGhpcyEK", buf.ptr);

	git_buf_free(&buf);
}
Esempio n. 10
0
int git_path_diriter_init(
	git_path_diriter *diriter,
	const char *path,
	unsigned int flags)
{
	assert(diriter && path);

	memset(diriter, 0, sizeof(git_path_diriter));

	if (git_buf_puts(&diriter->path, path) < 0)
		return -1;

	git_path_trim_slashes(&diriter->path);

	if (diriter->path.size == 0) {
		giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path);
		return -1;
	}

	if ((diriter->dir = opendir(diriter->path.ptr)) == NULL) {
		git_buf_free(&diriter->path);

		giterr_set(GITERR_OS, "Failed to open directory '%s'", path);
		return -1;
	}

#ifdef GIT_USE_ICONV
	if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
		(void)git_path_iconv_init_precompose(&diriter->ic);
#endif

	diriter->parent_len = diriter->path.size;
	diriter->flags = flags;

	return 0;
}
Esempio n. 11
0
void test_checkout_index__writes_conflict_file(void)
{
	git_index *index;
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_buf conflicting_buf = GIT_BUF_INIT;

	cl_git_pass(git_repository_index(&index, g_repo));

	add_conflict(index, "conflicting.txt");
	cl_git_pass(git_index_write(index));

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

	cl_git_pass(git_futils_readbuffer(&conflicting_buf, "testrepo/conflicting.txt"));
	cl_assert(strcmp(conflicting_buf.ptr,
		"<<<<<<< ours\n"
		"this file is changed in master and branch\n"
		"=======\n"
		"this file is changed in branch and master\n"
		">>>>>>> theirs\n") == 0);
	git_buf_free(&conflicting_buf);

	git_index_free(index);
}
Esempio n. 12
0
void test_config_read__path(void)
{
	git_config *cfg;
	git_buf path = GIT_BUF_INIT;
	git_buf old_path = GIT_BUF_INIT;
	git_buf home_path = GIT_BUF_INIT;
	git_buf expected_path = GIT_BUF_INIT;

	cl_git_pass(p_mkdir("fakehome", 0777));
	cl_git_pass(git_path_prettify(&home_path, "fakehome", NULL));
	cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &old_path));
	cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, home_path.ptr));
	cl_git_mkfile("./testconfig", "[some]\n path = ~/somefile");
	cl_git_pass(git_path_join_unrooted(&expected_path, "somefile", home_path.ptr, NULL));

	cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
	cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
	cl_assert_equal_s(expected_path.ptr, path.ptr);
	git_buf_free(&path);

	cl_git_mkfile("./testconfig", "[some]\n path = ~/");
	cl_git_pass(git_path_join_unrooted(&expected_path, "", home_path.ptr, NULL));

	cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
	cl_assert_equal_s(expected_path.ptr, path.ptr);
	git_buf_free(&path);

	cl_git_mkfile("./testconfig", "[some]\n path = ~");
	cl_git_pass(git_buf_sets(&expected_path, home_path.ptr));

	cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
	cl_assert_equal_s(expected_path.ptr, path.ptr);
	git_buf_free(&path);

	cl_git_mkfile("./testconfig", "[some]\n path = ~user/foo");
	cl_git_fail(git_config_get_path(&path, cfg, "some.path"));

	cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, old_path.ptr));
	git_buf_free(&old_path);
	git_buf_free(&home_path);
	git_buf_free(&expected_path);
	git_config_free(cfg);
}
Esempio n. 13
0
/* git revert --no-commit 72333f47d4e83616630ff3b0ffe4c0faebcc3c45 */
void test_revert_workdir__conflicts(void)
{
	git_reference *head_ref;
	git_commit *head, *commit;
	git_oid revert_oid;
	git_buf conflicting_buf = GIT_BUF_INIT, mergemsg_buf = GIT_BUF_INIT;

	struct merge_index_entry merge_index_entries[] = {
		{ 0100644, "7731926a337c4eaba1e2187d90ebfa0a93659382", 1, "file1.txt" },
		{ 0100644, "4b8fcff56437e60f58e9a6bc630dd242ebf6ea2c", 2, "file1.txt" },
		{ 0100644, "3a3ef367eaf3fe79effbfb0a56b269c04c2b59fe", 3, "file1.txt" },
		{ 0100644, "0ab09ea6d4c3634bdf6c221626d8b6f7dd890767", 0, "file2.txt" },
		{ 0100644, "f4e107c230d08a60fb419d19869f1f282b272d9c", 0, "file3.txt" },
		{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 0, "file6.txt" },
	};

	git_oid_fromstr(&revert_oid, "72333f47d4e83616630ff3b0ffe4c0faebcc3c45");

	cl_git_pass(git_repository_head(&head_ref, repo));
	cl_git_pass(git_reference_peel((git_object **)&head, head_ref, GIT_OBJ_COMMIT));
	cl_git_pass(git_reset(repo, (git_object *)head, GIT_RESET_HARD, NULL));

	cl_git_pass(git_commit_lookup(&commit, repo, &revert_oid));
	cl_git_pass(git_revert(repo, commit, NULL));

	cl_assert(merge_test_index(repo_index, merge_index_entries, 6));

	cl_git_pass(git_futils_readbuffer(&conflicting_buf,
		TEST_REPO_PATH "/file1.txt"));
	cl_assert(strcmp(conflicting_buf.ptr, "!File one!\n" \
		"!File one!\n" \
		"File one!\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		"<<<<<<< HEAD\n" \
		"File one!\n" \
		"!File one!\n" \
		"!File one!\n" \
		"!File one!\n" \
		"=======\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		"File one\n" \
		">>>>>>> parent of 72333f4... automergeable changes\n") == 0);

	cl_assert(git_path_exists(TEST_REPO_PATH "/.git/MERGE_MSG"));
	cl_git_pass(git_futils_readbuffer(&mergemsg_buf,
		TEST_REPO_PATH "/.git/MERGE_MSG"));
	cl_assert(strcmp(mergemsg_buf.ptr,
		"Revert \"automergeable changes\"\n" \
		"\n" \
		"This reverts commit 72333f47d4e83616630ff3b0ffe4c0faebcc3c45.\n"
		"\n" \
		"Conflicts:\n" \
		"\tfile1.txt\n") == 0);

	git_commit_free(commit);
	git_commit_free(head);
	git_reference_free(head_ref);
	git_buf_free(&mergemsg_buf);
	git_buf_free(&conflicting_buf);
}
Esempio n. 14
0
static int winhttp_stream_connect(winhttp_stream *s)
{
	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
	git_buf buf = GIT_BUF_INIT;
	char *proxy_url = NULL;
	wchar_t ct[MAX_CONTENT_TYPE_LEN];
	LPCWSTR types[] = { L"*/*", NULL };
	BOOL peerdist = FALSE;
	int error = -1;
	unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
	int default_timeout = TIMEOUT_INFINITE;
	int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;

	/* Prepare URL */
	git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url);

	if (git_buf_oom(&buf))
		return -1;

	/* Convert URL to wide characters */
	if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) {
		giterr_set(GITERR_OS, "Failed to convert string to wide form");
		goto on_error;
	}

	/* Establish request */
	s->request = WinHttpOpenRequest(
			t->connection,
			s->verb,
			s->request_uri,
			NULL,
			WINHTTP_NO_REFERER,
			types,
			t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0);

	if (!s->request) {
		giterr_set(GITERR_OS, "Failed to open request");
		goto on_error;
	}

	if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP");
		goto on_error;
	}

	/* Set proxy if necessary */
	if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0)
		goto on_error;

	if (proxy_url) {
		WINHTTP_PROXY_INFO proxy_info;
		wchar_t *proxy_wide;

		/* Convert URL to wide characters */
		int proxy_wide_len = git__utf8_to_16_alloc(&proxy_wide, proxy_url);

		if (proxy_wide_len < 0) {
			giterr_set(GITERR_OS, "Failed to convert string to wide form");
			goto on_error;
		}

		/* Strip any trailing forward slash on the proxy URL;
		 * WinHTTP doesn't like it if one is present */
		if (proxy_wide_len > 1 && L'/' == proxy_wide[proxy_wide_len - 2])
			proxy_wide[proxy_wide_len - 2] = L'\0';

		proxy_info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
		proxy_info.lpszProxy = proxy_wide;
		proxy_info.lpszProxyBypass = NULL;

		if (!WinHttpSetOption(s->request,
			WINHTTP_OPTION_PROXY,
			&proxy_info,
			sizeof(WINHTTP_PROXY_INFO))) {
			giterr_set(GITERR_OS, "Failed to set proxy");
			git__free(proxy_wide);
			goto on_error;
		}

		git__free(proxy_wide);
	}

	/* Disable WinHTTP redirects so we can handle them manually. Why, you ask?
	 * http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2ff8879-ab9f-4218-8f09-16d25dff87ae
	 */
	if (!WinHttpSetOption(s->request,
		WINHTTP_OPTION_DISABLE_FEATURE,
		&disable_redirects,
		sizeof(disable_redirects))) {
			giterr_set(GITERR_OS, "Failed to disable redirects");
			goto on_error;
	}

	/* Strip unwanted headers (X-P2P-PeerDist, X-P2P-PeerDistEx) that WinHTTP
	 * adds itself. This option may not be supported by the underlying
	 * platform, so we do not error-check it */
	WinHttpSetOption(s->request,
		WINHTTP_OPTION_PEERDIST_EXTENSION_STATE,
		&peerdist,
		sizeof(peerdist));

	/* Send Pragma: no-cache header */
	if (!WinHttpAddRequestHeaders(s->request, pragma_nocache, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) {
		giterr_set(GITERR_OS, "Failed to add a header to the request");
		goto on_error;
	}

	if (post_verb == s->verb) {
		/* Send Content-Type and Accept headers -- only necessary on a POST */
		git_buf_clear(&buf);
		if (git_buf_printf(&buf,
			"Content-Type: application/x-git-%s-request",
			s->service) < 0)
			goto on_error;

		if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
			giterr_set(GITERR_OS, "Failed to convert content-type to wide characters");
			goto on_error;
		}

		if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
			WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
			giterr_set(GITERR_OS, "Failed to add a header to the request");
			goto on_error;
		}

		git_buf_clear(&buf);
		if (git_buf_printf(&buf,
			"Accept: application/x-git-%s-result",
			s->service) < 0)
			goto on_error;

		if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
			giterr_set(GITERR_OS, "Failed to convert accept header to wide characters");
			goto on_error;
		}

		if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
			WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
			giterr_set(GITERR_OS, "Failed to add a header to the request");
			goto on_error;
		}
	}

	/* If requested, disable certificate validation */
	if (t->connection_data.use_ssl) {
		int flags;

		if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0)
			goto on_error;
	}

	/* If we have a credential on the subtransport, apply it to the request */
	if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
		t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC &&
		apply_basic_credential(s->request, t->cred) < 0)
		goto on_error;
	else if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_DEFAULT &&
		t->auth_mechanism == GIT_WINHTTP_AUTH_NEGOTIATE &&
		apply_default_credentials(s->request) < 0)
		goto on_error;

	/* If no other credentials have been applied and the URL has username and
	 * password, use those */
	if (!t->cred && t->connection_data.user && t->connection_data.pass) {
		if (!t->url_cred &&
			git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0)
			goto on_error;
		if (apply_basic_credential(s->request, t->url_cred) < 0)
			goto on_error;
	}

	/* We've done everything up to calling WinHttpSendRequest. */

	error = 0;

on_error:
	if (error < 0)
		winhttp_stream_close(s);

	git__free(proxy_url);
	git_buf_free(&buf);
	return error;
}
Esempio n. 15
0
static int filter_apply(
	git_filter				*self,
	void					**payload, /* may be read and/or set */
	git_buf					*to,
	const git_buf			*from,
	const git_filter_source	*src)
{
	struct filter_filter *ffs = (struct filter_filter *)self;
	git_config *config;
	git_buf configKey = GIT_BUF_INIT;
	int isRequired = FALSE;
	int error;
	const char *cmd = NULL;
	git_buf cmdBuf = GIT_BUF_INIT;
	wchar_t *wide_cmd;
	COMMAND_HANDLE commandHandle = COMMAND_HANDLE_INIT;
	git_buf errBuf = GIT_BUF_INIT;
	DWORD exitCode;

	if (!*payload)
		return GIT_PASSTHROUGH;

	if (git_repository_config__weakptr(&config, git_filter_source_repo(src)))
		return -1;

	git_buf_join3(&configKey, '.', "filter", *payload, "required");
	if (git_buf_oom(&configKey)) {
		giterr_set_oom();
		return -1;
	}

	error = git_config_get_bool(&isRequired, config, configKey.ptr);
	git_buf_free(&configKey);
	if (error && error != GIT_ENOTFOUND)
		return -1;

	git_buf_join(&configKey, '.', "filter", *payload);
	if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) {
		git_buf_puts(&configKey, ".smudge");
	} else {
		git_buf_puts(&configKey, ".clean");
	}
	if (git_buf_oom(&configKey)) {
		giterr_set_oom();
		return -1;
	}

	error = git_config_get_string(&cmd, config, configKey.ptr);
	git_buf_free(&configKey);
	if (error && error != GIT_ENOTFOUND)
		return -1;

	if (error == GIT_ENOTFOUND) {
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}

	git_buf_puts(&cmdBuf, cmd);
	if (git_buf_oom(&cmdBuf)) {
		giterr_set_oom();
		return -1;
	}

	if (expandPerCentF(&cmdBuf, git_filter_source_path(src)))
		return -1;

	if (ffs->shexepath) {
		// build params for sh.exe
		git_buf shParams = GIT_BUF_INIT;
		git_buf_puts(&shParams, " -c \"");
		git_buf_text_puts_escaped(&shParams, cmdBuf.ptr, "\"\\", "\\");
		git_buf_puts(&shParams, "\"");
		if (git_buf_oom(&shParams)) {
			git_buf_free(&cmdBuf);
			giterr_set_oom();
			return -1;
		}
		git_buf_swap(&shParams, &cmdBuf);
		git_buf_free(&shParams);
	}

	if (git__utf8_to_16_alloc(&wide_cmd, cmdBuf.ptr) < 0)
	{
		git_buf_free(&cmdBuf);
		giterr_set_oom();
		return -1;
	}
	git_buf_free(&cmdBuf);

	if (ffs->shexepath) {
		// build cmd, i.e. shexepath + params
		size_t len = wcslen(ffs->shexepath) + wcslen(wide_cmd) + 1;
		wchar_t *tmp = git__calloc(len, sizeof(wchar_t));
		if (!tmp) {
			git__free(wide_cmd);
			giterr_set_oom();
			return -1;
		}
		wcscat_s(tmp, len, ffs->shexepath);
		wcscat_s(tmp, len, wide_cmd);
		git__free(wide_cmd);
		wide_cmd = tmp;
	}

	commandHandle.errBuf = &errBuf;
	if (command_start(wide_cmd, &commandHandle, ffs->pEnv)) {
		git__free(wide_cmd);
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}
	git__free(wide_cmd);

	if (commmand_start_stdout_reading_thread(&commandHandle, to)) {
		command_close(&commandHandle);
		return -1;
	}

	if (command_write_gitbuf(&commandHandle, from)) {
		DWORD exitCode = command_close(&commandHandle);
		if (exitCode)
			setProcessError(exitCode, &errBuf);
		git_buf_free(&errBuf);
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}
	command_close_stdin(&commandHandle);

	if (command_wait_stdout_reading_thread(&commandHandle)) {
		DWORD exitCode = command_close(&commandHandle);
		if (exitCode)
			setProcessError(exitCode, &errBuf);
		git_buf_free(&errBuf);
		if (isRequired)
			return -1;
		return GIT_PASSTHROUGH;
	}

	exitCode = command_close(&commandHandle);
	if (exitCode) {
		if (isRequired) {
			setProcessError(exitCode, &errBuf);
			git_buf_free(&errBuf);
			return -1;
		}
		git_buf_free(&errBuf);
		return GIT_PASSTHROUGH;
	}

	git_buf_free(&errBuf);

	return 0;
}
Esempio n. 16
0
void test_repo_discover__0(void)
{
   // test discover
	git_repository *repo;
	git_buf ceiling_dirs_buf = GIT_BUF_INIT;
	const char *ceiling_dirs;
	char repository_path[GIT_PATH_MAX];
	char sub_repository_path[GIT_PATH_MAX];
	char found_path[GIT_PATH_MAX];
	const mode_t mode = 0777;

	git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode);
	append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER);
	ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);

	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));

	cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1));
	cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs));
	git_repository_free(repo);

	cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
	cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
	cl_git_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));

	cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode));
	ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path);

	cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode));
	write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
	write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT);
	write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../");
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);

	cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode));
	write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:");
	cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2, NULL, mode));
	write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:");
	cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3, NULL, mode));
	write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n");
	cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode));
	write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist");
	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
	cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));

	append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER);
	ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);

	//this must pass as ceiling_directories cannot predent the current
	//working directory to be checked
	cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
	cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));

	//.gitfile redirection should not be affected by ceiling directories
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path);
	ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path);

	cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES));
	git_repository_free(repo);
	git_buf_free(&ceiling_dirs_buf);
}
Esempio n. 17
0
int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refname)
{
	git_strarray remote_list = {0};
	size_t i;
	git_remote *remote;
	const git_refspec *fetchspec;
	int error = 0;
	char *remote_name = NULL;

	assert(buf && repo && refname);

	git_buf_sanitize(buf);

	/* Verify that this is a remote branch */
	if (!git_reference__is_remote(refname)) {
		giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.",
			refname);
		error = GIT_ERROR;
		goto cleanup;
	}

	/* Get the remotes */
	if ((error = git_remote_list(&remote_list, repo)) < 0)
		goto cleanup;

	/* Find matching remotes */
	for (i = 0; i < remote_list.count; i++) {
		if ((error = git_remote_lookup(&remote, repo, remote_list.strings[i])) < 0)
			continue;

		fetchspec = git_remote__matching_dst_refspec(remote, refname);
		if (fetchspec) {
			/* If we have not already set out yet, then set
			 * it to the matching remote name. Otherwise
			 * multiple remotes match this reference, and it
			 * is ambiguous. */
			if (!remote_name) {
				remote_name = remote_list.strings[i];
			} else {
				git_remote_free(remote);

				giterr_set(GITERR_REFERENCE,
					"Reference '%s' is ambiguous", refname);
				error = GIT_EAMBIGUOUS;
				goto cleanup;
			}
		}

		git_remote_free(remote);
	}

	if (remote_name) {
		git_buf_clear(buf);
		error = git_buf_puts(buf, remote_name);
	} else {
		giterr_set(GITERR_REFERENCE,
			"Could not determine remote for '%s'", refname);
		error = GIT_ENOTFOUND;
	}

cleanup:
	if (error < 0)
		git_buf_free(buf);

	git_strarray_free(&remote_list);
	return error;
}
Esempio n. 18
0
void test_submodule_nosubs__add_and_delete(void)
{
    git_repository *repo = cl_git_sandbox_init("status");
    git_submodule *sm;
    git_buf buf = GIT_BUF_INIT;

    /* note lack of calls to git_submodule_reload_all - this *should* work */

    cl_git_fail(git_submodule_lookup(NULL, repo, "libgit2"));
    cl_git_fail(git_submodule_lookup(NULL, repo, "submodules/libgit2"));

    /* create */

    cl_git_pass(git_submodule_add_setup(
                    &sm, repo, "https://github.com/libgit2/libgit2.git", "submodules/libgit2", 1));
    cl_assert_equal_s("submodules/libgit2", git_submodule_name(sm));
    cl_assert_equal_s("submodules/libgit2", git_submodule_path(sm));
    git_submodule_free(sm);

    cl_git_pass(git_futils_readbuffer(&buf, "status/.gitmodules"));
    cl_assert(strstr(buf.ptr, "[submodule \"submodules/libgit2\"]") != NULL);
    cl_assert(strstr(buf.ptr, "path = submodules/libgit2") != NULL);
    git_buf_free(&buf);

    /* lookup */

    cl_git_fail(git_submodule_lookup(&sm, repo, "libgit2"));
    cl_git_pass(git_submodule_lookup(&sm, repo, "submodules/libgit2"));
    cl_assert_equal_s("submodules/libgit2", git_submodule_name(sm));
    cl_assert_equal_s("submodules/libgit2", git_submodule_path(sm));
    git_submodule_free(sm);

    /* update name */

    cl_git_rewritefile(
        "status/.gitmodules",
        "[submodule \"libgit2\"]\n"
        "  path = submodules/libgit2\n"
        "  url = https://github.com/libgit2/libgit2.git\n");

    cl_git_pass(git_submodule_lookup(&sm, repo, "libgit2"));
    cl_assert_equal_s("libgit2", git_submodule_name(sm));
    cl_assert_equal_s("submodules/libgit2", git_submodule_path(sm));
    git_submodule_free(sm);
    cl_git_pass(git_submodule_lookup(&sm, repo, "submodules/libgit2"));
    git_submodule_free(sm);

    /* revert name update */

    cl_git_rewritefile(
        "status/.gitmodules",
        "[submodule \"submodules/libgit2\"]\n"
        "  path = submodules/libgit2\n"
        "  url = https://github.com/libgit2/libgit2.git\n");

    cl_git_fail(git_submodule_lookup(&sm, repo, "libgit2"));
    cl_git_pass(git_submodule_lookup(&sm, repo, "submodules/libgit2"));
    git_submodule_free(sm);

    /* remove completely */

    cl_must_pass(p_unlink("status/.gitmodules"));
    cl_git_fail(git_submodule_lookup(&sm, repo, "libgit2"));
    cl_git_fail(git_submodule_lookup(&sm, repo, "submodules/libgit2"));
}
Esempio n. 19
0
/**
 * Merge branch into HEAD
 *
 * @param branch S4 class git_branch to merge into HEAD.
 * @param merger Who is performing the merge
 * @param commit_on_success Commit merge commit, if one was created
 * during a normal merge
 * @return S4 class git_merge_result
 */
SEXP git2r_merge_branch(SEXP branch, SEXP merger, SEXP commit_on_success)
{
    int err;
    SEXP result = R_NilValue;
    const char *name;
    git_buf buf = GIT_BUF_INIT;
    git_branch_t type;
    git_annotated_commit **merge_heads = NULL;
    git_reference *reference = NULL;
    git_repository *repository = NULL;
    git_signature *who = NULL;

    if (git2r_arg_check_branch(branch))
        git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg);
    if (git2r_arg_check_logical(commit_on_success))
        git2r_error(__func__, NULL, "'commit_on_success'", git2r_err_logical_arg);
    if (git2r_arg_check_signature(merger))
        git2r_error(__func__, NULL, "'merger'", git2r_err_signature_arg);

    err = git2r_signature_from_arg(&who, merger);
    if (err)
        goto cleanup;

    repository = git2r_repository_open(GET_SLOT(branch, Rf_install("repo")));
    if (!repository)
        git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);

    name = CHAR(STRING_ELT(GET_SLOT(branch, Rf_install("name")), 0));
    type = INTEGER(GET_SLOT(branch, Rf_install("type")))[0];
    err = git_branch_lookup(&reference, repository, name, type);
    if (err)
        goto cleanup;

    merge_heads = calloc(1, sizeof(git_annotated_commit*));
    if (NULL == merge_heads) {
        giterr_set_str(GITERR_NONE, git2r_err_alloc_memory_buffer);
        goto cleanup;
    }

    err = git_annotated_commit_from_ref(
        &(merge_heads[0]),
        repository,
        reference);
    if (err)
        goto cleanup;

    err = git_buf_printf(&buf, "merge %s", name);
    if (err)
        goto cleanup;

    PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_merge_result")));
    err = git2r_merge(
        result,
        repository,
        (const git_annotated_commit **)merge_heads,
        1,
        GIT_MERGE_PREFERENCE_NONE,
        buf.ptr,
        who,
        LOGICAL(commit_on_success)[0]);

cleanup:
    git_buf_free(&buf);

    if (who)
        git_signature_free(who);

    if (merge_heads)
        git2r_merge_heads_free(merge_heads, 1);

    if (reference)
        git_reference_free(reference);

    if (repository)
        git_repository_free(repository);

    if (R_NilValue != result)
        UNPROTECT(1);

    if (err)
        git2r_error(__func__, giterr_last(), NULL, NULL);

    return result;
}
Esempio n. 20
0
static int update_head_to_remote(
		git_repository *repo,
		git_remote *remote,
		const git_signature *signature,
		const char *reflog_message)
{
	int error = 0, found_branch = 0;
	size_t refs_len;
	git_refspec dummy_spec, *refspec;
	const git_remote_head *remote_head, **refs;
	const git_oid *remote_head_id;
	git_buf remote_master_name = GIT_BUF_INIT;
	git_buf branch = GIT_BUF_INIT;

	if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
		return error;

	/* Did we just clone an empty repository? */
	if (refs_len == 0)
		return setup_tracking_config(
			repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);

	error = git_remote_default_branch(&branch, remote);
	if (error == GIT_ENOTFOUND) {
		git_buf_puts(&branch, GIT_REFS_HEADS_MASTER_FILE);
	} else {
		found_branch = 1;
	}

	/* Get the remote's HEAD. This is always the first ref in the list. */
	remote_head = refs[0];
	assert(remote_head);

	remote_head_id = &remote_head->oid;
	refspec = git_remote__matching_refspec(remote, git_buf_cstr(&branch));

	if (refspec == NULL) {
		memset(&dummy_spec, 0, sizeof(git_refspec));
		refspec = &dummy_spec;
	}

	/* Determine the remote tracking reference name from the local master */
	if ((error = git_refspec_transform(
		&remote_master_name,
		refspec,
		git_buf_cstr(&branch))) < 0)
		return error;

	if (found_branch) {
		error = update_head_to_new_branch(
			repo,
			remote_head_id,
			git_buf_cstr(&branch),
			signature, reflog_message);
	} else {
		error = git_repository_set_head_detached(
			repo, remote_head_id, signature, reflog_message);
	}

	git_buf_free(&remote_master_name);
	git_buf_free(&branch);
	return error;
}
Esempio n. 21
0
/**
 * Perform a fast-forward merge
 *
 * @param merge_result S4 class git_merge_result
 * @param merge_head The merge head to fast-forward merge
 * @param repository The repository
 * @param log_message First part of the one line long message in the reflog
 * @return 0 on success, or error code
 */
static int git2r_fast_forward_merge(
    SEXP merge_result,
    const git_annotated_commit *merge_head,
    git_repository *repository,
    const char *log_message)
{
    int err;
    const git_oid *oid;
    git_buf buf = GIT_BUF_INIT;
    git_commit *commit = NULL;
    git_tree *tree = NULL;
    git_reference *reference = NULL;
    git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;

    oid = git_annotated_commit_id(merge_head);
    err = git_commit_lookup(&commit, repository, oid);
    if (err)
        goto cleanup;

    err = git_commit_tree(&tree, commit);
    if (err)
        goto cleanup;

    opts.checkout_strategy = GIT_CHECKOUT_SAFE;
    err = git_checkout_tree(repository, (git_object*)tree, &opts);
    if (err)
        goto cleanup;

    err = git_repository_head(&reference, repository);
    if (err) {
        if (GIT_ENOTFOUND != err)
            goto cleanup;
    }

    err = git_buf_printf(&buf, "%s: Fast-forward", log_message);
    if (err)
        goto cleanup;

    if (GIT_ENOTFOUND == err) {
        err = git_reference_create(
            &reference,
            repository,
            "HEAD",
            git_commit_id(commit),
            0, /* force */
            buf.ptr);
    } else {
        git_reference *target_ref = NULL;

        err = git_reference_set_target(
            &target_ref,
            reference,
            git_commit_id(commit),
            buf.ptr);

        if (target_ref)
            git_reference_free(target_ref);
    }

    SET_SLOT(
        merge_result,
        Rf_install("fast_forward"),
        ScalarLogical(1));

    SET_SLOT(
        merge_result,
        Rf_install("conflicts"),
        ScalarLogical(0));

cleanup:
    git_buf_free(&buf);

    if (commit)
        git_commit_free(commit);

    if (reference)
        git_reference_free(reference);

    if (tree)
        git_tree_free(tree);

    return err;
}
Esempio n. 22
0
static int update_head_to_remote(git_repository *repo, git_remote *remote)
{
	int retcode = -1;
	git_refspec dummy_spec;
	git_remote_head *remote_head;
	struct head_info head_info;
	git_buf remote_master_name = GIT_BUF_INIT;

	/* Did we just clone an empty repository? */
	if (remote->refs.length == 0) {
		return setup_tracking_config(
			repo,
			"master",
			GIT_REMOTE_ORIGIN,
			GIT_REFS_HEADS_MASTER_FILE);
	}

	/* Get the remote's HEAD. This is always the first ref in remote->refs. */
	remote_head = NULL;

	if (!remote->transport->ls(remote->transport, get_head_callback, &remote_head))
		return -1;

	assert(remote_head);

	git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid);
	git_buf_init(&head_info.branchname, 16);
	head_info.repo = repo;
	head_info.refspec = git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
	head_info.found = 0;

	if (head_info.refspec == NULL) {
		memset(&dummy_spec, 0, sizeof(git_refspec));
		head_info.refspec = &dummy_spec;
	}

	/* Determine the remote tracking reference name from the local master */
	if (git_refspec_transform_r(
		&remote_master_name,
		head_info.refspec,
		GIT_REFS_HEADS_MASTER_FILE) < 0)
			return -1;

	/* Check to see if the remote HEAD points to the remote master */
	if (reference_matches_remote_head(git_buf_cstr(&remote_master_name), &head_info) < 0)
		goto cleanup;

	if (head_info.found) {
		retcode = update_head_to_new_branch(
			repo,
			&head_info.remote_head_oid,
			git_buf_cstr(&head_info.branchname));

		goto cleanup;
	}

	/* Not master. Check all the other refs. */
	if (git_reference_foreach_name(
		repo,
		reference_matches_remote_head,
		&head_info) < 0)
			goto cleanup;

	if (head_info.found) {
		retcode = update_head_to_new_branch(
			repo,
			&head_info.remote_head_oid,
			git_buf_cstr(&head_info.branchname));

		goto cleanup;
	} else {
		retcode = git_repository_set_head_detached(
			repo,
			&head_info.remote_head_oid);
		goto cleanup;
	}

cleanup:
	git_buf_free(&remote_master_name);
	git_buf_free(&head_info.branchname);
	return retcode;
}
Esempio n. 23
0
int git_futils_mkdir(
	const char *path,
	const char *base,
	mode_t mode,
	uint32_t flags)
{
	int error = -1;
	git_buf make_path = GIT_BUF_INIT;
	ssize_t root = 0, min_root_len;
	char lastch = '/', *tail;
	struct stat st;

	/* build path and find "root" where we should start calling mkdir */
	if (git_path_join_unrooted(&make_path, path, base, &root) < 0)
		return -1;

	if (make_path.size == 0) {
		giterr_set(GITERR_OS, "Attempt to create empty path");
		goto done;
	}

	/* remove trailing slashes on path */
	while (make_path.ptr[make_path.size - 1] == '/') {
		make_path.size--;
		make_path.ptr[make_path.size] = '\0';
	}

	/* if we are not supposed to made the last element, truncate it */
	if ((flags & GIT_MKDIR_SKIP_LAST2) != 0) {
		git_buf_rtruncate_at_char(&make_path, '/');
		flags |= GIT_MKDIR_SKIP_LAST;
	}
	if ((flags & GIT_MKDIR_SKIP_LAST) != 0)
		git_buf_rtruncate_at_char(&make_path, '/');

	/* if nothing left after truncation, then we're done! */
	if (!make_path.size) {
		error = 0;
		goto done;
	}

	/* if we are not supposed to make the whole path, reset root */
	if ((flags & GIT_MKDIR_PATH) == 0)
		root = git_buf_rfind(&make_path, '/');

	/* advance root past drive name or network mount prefix */
	min_root_len = git_path_root(make_path.ptr);
	if (root < min_root_len)
		root = min_root_len;
	while (root >= 0 && make_path.ptr[root] == '/')
		++root;

	/* clip root to make_path length */
	if (root > (ssize_t)make_path.size)
		root = (ssize_t)make_path.size; /* i.e. NUL byte of string */
	if (root < 0)
		root = 0;

	/* walk down tail of path making each directory */
	for (tail = &make_path.ptr[root]; *tail; *tail = lastch) {

		/* advance tail to include next path component */
		while (*tail == '/')
			tail++;
		while (*tail && *tail != '/')
			tail++;

		/* truncate path at next component */
		lastch = *tail;
		*tail = '\0';
		st.st_mode = 0;

		/* make directory */
		if (p_mkdir(make_path.ptr, mode) < 0) {
			int tmp_errno = giterr_system_last();

			/* ignore error if not at end or if directory already exists */
			if (lastch == '\0' &&
				(p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode))) {
				giterr_system_set(tmp_errno);
				giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
				goto done;
			}

			/* with exclusive create, existing dir is an error */
			if ((flags & GIT_MKDIR_EXCL) != 0) {
				giterr_set(GITERR_OS, "Directory already exists '%s'", make_path.ptr);
				error = GIT_EEXISTS;
				goto done;
			}
		}

		/* chmod if requested and necessary */
		if (((flags & GIT_MKDIR_CHMOD_PATH) != 0 ||
			 (lastch == '\0' && (flags & GIT_MKDIR_CHMOD) != 0)) &&
			st.st_mode != mode &&
			(error = p_chmod(make_path.ptr, mode)) < 0 &&
			lastch == '\0') {
			giterr_set(GITERR_OS, "Failed to set permissions on '%s'", make_path.ptr);
			goto done;
		}
	}

	error = 0;

	/* check that full path really is a directory if requested & needed */
	if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 &&
		lastch != '\0' &&
		(p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode))) {
		giterr_set(GITERR_OS, "Path is not a directory '%s'", make_path.ptr);
		error = GIT_ENOTFOUND;
	}

done:
	git_buf_free(&make_path);
	return error;
}
Esempio n. 24
0
/* Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 */
int git_reference__normalize_name(
	git_buf *buf,
	const char *name,
	unsigned int flags)
{
	const char *current;
	int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC;
	unsigned int process_flags;
	bool normalize = (buf != NULL);

#ifdef GIT_USE_ICONV
	git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
#endif

	assert(name);

	process_flags = flags;
	current = (char *)name;

	if (*current == '/')
		goto cleanup;

	if (normalize)
		git_buf_clear(buf);

#ifdef GIT_USE_ICONV
	if ((flags & GIT_REF_FORMAT__PRECOMPOSE_UNICODE) != 0) {
		size_t namelen = strlen(current);
		if ((error = git_path_iconv_init_precompose(&ic)) < 0 ||
			(error = git_path_iconv(&ic, &current, &namelen)) < 0)
			goto cleanup;
		error = GIT_EINVALIDSPEC;
	}
#endif

	while (true) {
		segment_len = ensure_segment_validity(current);
		if (segment_len < 0) {
			if ((process_flags & GIT_REF_FORMAT_REFSPEC_PATTERN) &&
					current[0] == '*' &&
					(current[1] == '\0' || current[1] == '/')) {
				/* Accept one wildcard as a full refname component. */
				process_flags &= ~GIT_REF_FORMAT_REFSPEC_PATTERN;
				segment_len = 1;
			} else
				goto cleanup;
		}

		if (segment_len > 0) {
			if (normalize) {
				size_t cur_len = git_buf_len(buf);

				git_buf_joinpath(buf, git_buf_cstr(buf), current);
				git_buf_truncate(buf,
					cur_len + segment_len + (segments_count ? 1 : 0));

				if (git_buf_oom(buf)) {
					error = -1;
					goto cleanup;
				}
			}

			segments_count++;
		}

		/* No empty segment is allowed when not normalizing */
		if (segment_len == 0 && !normalize)
			goto cleanup;

		if (current[segment_len] == '\0')
			break;

		current += segment_len + 1;
	}

	/* A refname can not be empty */
	if (segment_len == 0 && segments_count == 0)
		goto cleanup;

	/* A refname can not end with "." */
	if (current[segment_len - 1] == '.')
		goto cleanup;

	/* A refname can not end with "/" */
	if (current[segment_len - 1] == '/')
		goto cleanup;

	if ((segments_count == 1 ) && !(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL))
		goto cleanup;

	if ((segments_count == 1 ) &&
	    !(flags & GIT_REF_FORMAT_REFSPEC_SHORTHAND) &&
		!(is_all_caps_and_underscore(name, (size_t)segment_len) ||
			((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name))))
			goto cleanup;

	if ((segments_count > 1)
		&& (is_all_caps_and_underscore(name, strchr(name, '/') - name)))
			goto cleanup;

	error = 0;

cleanup:
	if (error == GIT_EINVALIDSPEC)
		giterr_set(
			GITERR_REFERENCE,
			"The given reference name '%s' is not valid", name);

	if (error && normalize)
		git_buf_free(buf);

#ifdef GIT_USE_ICONV
	git_path_iconv_clear(&ic);
#endif

	return error;
}
Esempio n. 25
0
/* rewrite gitmodules -> .gitmodules
 * rewrite the empty or relative urls inside each module
 * rename the .gitted directory inside any submodule to .git
 */
void rewrite_gitmodules(const char *workdir)
{
	git_buf in_f = GIT_BUF_INIT, out_f = GIT_BUF_INIT, path = GIT_BUF_INIT;
	FILE *in, *out;
	char line[256];

	cl_git_pass(git_buf_joinpath(&in_f, workdir, "gitmodules"));
	cl_git_pass(git_buf_joinpath(&out_f, workdir, ".gitmodules"));

	cl_assert((in  = fopen(in_f.ptr, "rb")) != NULL);
	cl_assert((out = fopen(out_f.ptr, "wb")) != NULL);

	while (fgets(line, sizeof(line), in) != NULL) {
		char *scan = line;

		while (*scan == ' ' || *scan == '\t') scan++;

		/* rename .gitted -> .git in submodule directories */
		if (git__prefixcmp(scan, "path =") == 0) {
			scan += strlen("path =");
			while (*scan == ' ') scan++;

			git_buf_joinpath(&path, workdir, scan);
			git_buf_rtrim(&path);
			git_buf_joinpath(&path, path.ptr, ".gitted");

			if (!git_buf_oom(&path) && p_access(path.ptr, F_OK) == 0) {
				git_buf_joinpath(&out_f, workdir, scan);
				git_buf_rtrim(&out_f);
				git_buf_joinpath(&out_f, out_f.ptr, ".git");

				if (!git_buf_oom(&out_f))
					p_rename(path.ptr, out_f.ptr);
			}
		}

		/* copy non-"url =" lines verbatim */
		if (git__prefixcmp(scan, "url =") != 0) {
			fputs(line, out);
			continue;
		}

		/* convert relative URLs in "url =" lines */
		scan += strlen("url =");
		while (*scan == ' ') scan++;

		if (*scan == '.') {
			git_buf_joinpath(&path, workdir, scan);
			git_buf_rtrim(&path);
		} else if (!*scan || *scan == '\n') {
			git_buf_joinpath(&path, workdir, "../testrepo.git");
		} else {
			fputs(line, out);
			continue;
		}

		git_path_prettify(&path, path.ptr, NULL);
		git_buf_putc(&path, '\n');
		cl_assert(!git_buf_oom(&path));

		fwrite(line, scan - line, sizeof(char), out);
		fputs(path.ptr, out);
	}

	fclose(in);
	fclose(out);

	cl_must_pass(p_unlink(in_f.ptr));

	git_buf_free(&in_f);
	git_buf_free(&out_f);
	git_buf_free(&path);
}
Esempio n. 26
0
int git_reset(
	git_repository *repo,
	git_object *target,
	git_reset_t reset_type,
	git_checkout_options *checkout_opts,
	git_signature *signature,
	const char *log_message)
{
	git_object *commit = NULL;
	git_index *index = NULL;
	git_tree *tree = NULL;
	int error = 0;
	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
	git_buf log_message_buf = GIT_BUF_INIT;

	assert(repo && target);

	if (checkout_opts)
		opts = *checkout_opts;

	if (git_object_owner(target) != repo) {
		giterr_set(GITERR_OBJECT,
			"%s - The given target does not belong to this repository.", ERROR_MSG);
		return -1;
	}

	if (reset_type != GIT_RESET_SOFT &&
		(error = git_repository__ensure_not_bare(repo,
			reset_type == GIT_RESET_MIXED ? "reset mixed" : "reset hard")) < 0)
		return error;

	if ((error = git_object_peel(&commit, target, GIT_OBJ_COMMIT)) < 0 ||
		(error = git_repository_index(&index, repo)) < 0 ||
		(error = git_commit_tree(&tree, (git_commit *)commit)) < 0)
		goto cleanup;

	if (reset_type == GIT_RESET_SOFT &&
		(git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE ||
		 git_index_has_conflicts(index)))
	{
		giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge.", ERROR_MSG);
		error = GIT_EUNMERGED;
		goto cleanup;
	}

	if (log_message)
		git_buf_sets(&log_message_buf, log_message);
	else
		git_buf_sets(&log_message_buf, "reset: moving");

	/* move HEAD to the new target */
	if ((error = git_reference__update_terminal(repo, GIT_HEAD_FILE,
		git_object_id(commit), signature, git_buf_cstr(&log_message_buf))) < 0)
		goto cleanup;

	if (reset_type == GIT_RESET_HARD) {
		/* overwrite working directory with HEAD */
		opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_SKIP_UNMERGED;

		if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0)
			goto cleanup;
	}

	if (reset_type > GIT_RESET_SOFT) {
		/* reset index to the target content */

		if ((error = git_index_read_tree(index, tree)) < 0 ||
			(error = git_index_write(index)) < 0)
			goto cleanup;

		if ((error = git_repository_state_cleanup(repo)) < 0) {
			giterr_set(GITERR_INDEX, "%s - failed to clean up merge data", ERROR_MSG);
			goto cleanup;
		}
	}

cleanup:
	git_object_free(commit);
	git_index_free(index);
	git_tree_free(tree);
	git_buf_free(&log_message_buf);

	return error;
}
Esempio n. 27
0
int git_branch_upstream_name(
	git_buf *out,
	git_repository *repo,
	const char *refname)
{
	git_buf remote_name = GIT_BUF_INIT;
	git_buf merge_name = GIT_BUF_INIT;
	git_buf buf = GIT_BUF_INIT;
	int error = -1;
	git_remote *remote = NULL;
	const git_refspec *refspec;
	git_config *config;

	assert(out && refname);

	git_buf_sanitize(out);

	if (!git_reference__is_branch(refname))
		return not_a_local_branch(refname);

	if ((error = git_repository_config_snapshot(&config, repo)) < 0)
		return error;

	if ((error = retrieve_upstream_configuration(
		&remote_name, config, refname, "branch.%s.remote")) < 0)
			goto cleanup;

	if ((error = retrieve_upstream_configuration(
		&merge_name, config, refname, "branch.%s.merge")) < 0)
			goto cleanup;

	if (git_buf_len(&remote_name) == 0 || git_buf_len(&merge_name) == 0) {
		giterr_set(GITERR_REFERENCE,
			"branch '%s' does not have an upstream", refname);
		error = GIT_ENOTFOUND;
		goto cleanup;
	}

	if (strcmp(".", git_buf_cstr(&remote_name)) != 0) {
		if ((error = git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name))) < 0)
			goto cleanup;

		refspec = git_remote__matching_refspec(remote, git_buf_cstr(&merge_name));
		if (!refspec) {
			error = GIT_ENOTFOUND;
			goto cleanup;
		}

		if (git_refspec_transform(&buf, refspec, git_buf_cstr(&merge_name)) < 0)
			goto cleanup;
	} else
		if (git_buf_set(&buf, git_buf_cstr(&merge_name), git_buf_len(&merge_name)) < 0)
			goto cleanup;

	error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));

cleanup:
	git_config_free(config);
	git_remote_free(remote);
	git_buf_free(&remote_name);
	git_buf_free(&merge_name);
	git_buf_free(&buf);
	return error;
}
Esempio n. 28
0
static int git_commit__create_internal(
    git_oid *id,
    git_repository *repo,
    const char *update_ref,
    const git_signature *author,
    const git_signature *committer,
    const char *message_encoding,
    const char *message,
    const git_oid *tree,
    git_commit_parent_callback parent_cb,
    void *parent_payload,
    bool validate)
{
    git_reference *ref = NULL;
    int error = 0, matched_parent = 0;
    const git_oid *current_id = NULL;
    git_buf commit = GIT_BUF_INIT;
    size_t i = 0;
    git_odb *odb;
    const git_oid *parent;

    assert(id && repo && tree && parent_cb);

    if (validate && !git_object__is_valid(repo, tree, GIT_OBJ_TREE))
        return -1;

    if (update_ref) {
        error = git_reference_lookup_resolved(&ref, repo, update_ref, 10);
        if (error < 0 && error != GIT_ENOTFOUND)
            return error;
    }
    giterr_clear();

    if (ref)
        current_id = git_reference_target(ref);

    git_oid__writebuf(&commit, "tree ", tree);

    while ((parent = parent_cb(i, parent_payload)) != NULL) {
        if (validate && !git_object__is_valid(repo, parent, GIT_OBJ_COMMIT)) {
            error = -1;
            goto on_error;
        }

        git_oid__writebuf(&commit, "parent ", parent);
        if (i == 0 && current_id && git_oid_equal(current_id, parent))
            matched_parent = 1;
        i++;
    }

    if (ref && !matched_parent) {
        git_reference_free(ref);
        git_buf_free(&commit);
        giterr_set(GITERR_OBJECT, "failed to create commit: current tip is not the first parent");
        return GIT_EMODIFIED;
    }

    git_signature__writebuf(&commit, "author ", author);
    git_signature__writebuf(&commit, "committer ", committer);

    if (message_encoding != NULL)
        git_buf_printf(&commit, "encoding %s\n", message_encoding);

    git_buf_putc(&commit, '\n');

    if (git_buf_puts(&commit, message) < 0)
        goto on_error;

    if (git_repository_odb__weakptr(&odb, repo) < 0)
        goto on_error;

    if (git_odb_write(id, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT) < 0)
        goto on_error;

    git_buf_free(&commit);

    if (update_ref != NULL) {
        error = git_reference__update_for_commit(
                    repo, ref, update_ref, id, "commit");
        git_reference_free(ref);
        return error;
    }

    return 0;

on_error:
    git_buf_free(&commit);
    return -1;
}
Esempio n. 29
0
int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
{
	git_buf key = GIT_BUF_INIT, value = GIT_BUF_INIT;
	git_reference *upstream;
	git_repository *repo;
	git_remote *remote = NULL;
	git_config *config;
	const char *name, *shortname;
	int local, error;
	const git_refspec *fetchspec;

	name = git_reference_name(branch);
	if (!git_reference__is_branch(name))
		return not_a_local_branch(name);

	if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
		return -1;

	shortname = name + strlen(GIT_REFS_HEADS_DIR);

	if (upstream_name == NULL)
		return unset_upstream(config, shortname);

	repo = git_reference_owner(branch);

	/* First we need to figure out whether it's a branch or remote-tracking */
	if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_LOCAL) == 0)
		local = 1;
	else if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_REMOTE) == 0)
		local = 0;
	else {
		giterr_set(GITERR_REFERENCE,
			"Cannot set upstream for branch '%s'", shortname);
		return GIT_ENOTFOUND;
	}

	/*
	 * If it's local, the remote is "." and the branch name is
	 * simply the refname. Otherwise we need to figure out what
	 * the remote-tracking branch's name on the remote is and use
	 * that.
	 */
	if (local)
		error = git_buf_puts(&value, ".");
	else
		error = git_branch_remote_name(&value, repo, git_reference_name(upstream));

	if (error < 0)
		goto on_error;

	if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0)
		goto on_error;

	if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0)
		goto on_error;

	if (local) {
		git_buf_clear(&value);
		if (git_buf_puts(&value, git_reference_name(upstream)) < 0)
			goto on_error;
	} else {
		/* Get the remoe-tracking branch's refname in its repo */
		if (git_remote_lookup(&remote, repo, git_buf_cstr(&value)) < 0)
			goto on_error;

		fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
		git_buf_clear(&value);
		if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0)
			goto on_error;

		git_remote_free(remote);
		remote = NULL;
	}

	git_buf_clear(&key);
	if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0)
		goto on_error;

	if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0)
		goto on_error;

	git_reference_free(upstream);
	git_buf_free(&key);
	git_buf_free(&value);

	return 0;

on_error:
	git_reference_free(upstream);
	git_buf_free(&key);
	git_buf_free(&value);
	git_remote_free(remote);

	return -1;
}
Esempio n. 30
0
int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
{
	git_buf buf = GIT_BUF_INIT;
	size_t j, pos;
	git_remote_head key;

	const char* formatters[] = {
		GIT_REFS_DIR "%s",
		GIT_REFS_TAGS_DIR "%s",
		GIT_REFS_HEADS_DIR "%s",
		NULL
	};

	git_refspec *cur = git__calloc(1, sizeof(git_refspec));
	GITERR_CHECK_ALLOC(cur);

	cur->force = spec->force;
	cur->push = spec->push;
	cur->pattern = spec->pattern;
	cur->matching = spec->matching;
	cur->string = git__strdup(spec->string);

	/* shorthand on the lhs */
	if (git__prefixcmp(spec->src, GIT_REFS_DIR)) {
		for (j = 0; formatters[j]; j++) {
			git_buf_clear(&buf);
			if (git_buf_printf(&buf, formatters[j], spec->src) < 0)
				return -1;

			key.name = (char *) git_buf_cstr(&buf);
			if (!git_vector_search(&pos, refs, &key)) {
				/* we found something to match the shorthand, set src to that */
				cur->src = git_buf_detach(&buf);
			}
		}
	}

	/* No shorthands found, copy over the name */
	if (cur->src == NULL && spec->src != NULL) {
		cur->src = git__strdup(spec->src);
		GITERR_CHECK_ALLOC(cur->src);
	}

	if (spec->dst && git__prefixcmp(spec->dst, GIT_REFS_DIR)) {
		/* if it starts with "remotes" then we just prepend "refs/" */
		if (!git__prefixcmp(spec->dst, "remotes/")) {
			git_buf_puts(&buf, GIT_REFS_DIR);
		} else {
			git_buf_puts(&buf, GIT_REFS_HEADS_DIR);
		}

		if (git_buf_puts(&buf, spec->dst) < 0)
			return -1;

		cur->dst = git_buf_detach(&buf);
	}

	git_buf_free(&buf);

	if (cur->dst == NULL && spec->dst != NULL) {
		cur->dst = git__strdup(spec->dst);
		GITERR_CHECK_ALLOC(cur->dst);
	}

	return git_vector_insert(out, cur);
}