static int add_ref(transport_local *t, const char *name)
{
	const char peeled[] = "^{}";
	git_remote_head *head;
	git_object *obj = NULL, *target = NULL;
	git_transport *transport = (git_transport *) t;
	git_buf buf = GIT_BUF_INIT;
	git_pkt_ref *pkt;

	head = git__malloc(sizeof(git_remote_head));
	GITERR_CHECK_ALLOC(head);
	pkt = git__malloc(sizeof(git_pkt_ref));
	GITERR_CHECK_ALLOC(pkt);

	head->name = git__strdup(name);
	GITERR_CHECK_ALLOC(head->name);

	if (git_reference_name_to_oid(&head->oid, t->repo, name) < 0) {
		git__free(head);
		git__free(pkt->head.name);
		git__free(pkt);
	}

	pkt->type = GIT_PKT_REF;
	memcpy(&pkt->head, head, sizeof(git_remote_head));
	git__free(head);

	if (git_vector_insert(&transport->refs, pkt) < 0)
	{
		git__free(pkt->head.name);
		git__free(pkt);
		return -1;
	}

	/* If it's not a tag, we don't need to try to peel it */
	if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
		return 0;

	if (git_object_lookup(&obj, t->repo, &pkt->head.oid, GIT_OBJ_ANY) < 0)
		return -1;

	head = NULL;

	/* If it's not an annotated tag, just get out */
	if (git_object_type(obj) != GIT_OBJ_TAG) {
		git_object_free(obj);
		return 0;
	}

	/* And if it's a tag, peel it, and add it to the list */
	head = git__malloc(sizeof(git_remote_head));
	GITERR_CHECK_ALLOC(head);
	if (git_buf_join(&buf, 0, name, peeled) < 0)
		return -1;

	head->name = git_buf_detach(&buf);

	pkt = git__malloc(sizeof(git_pkt_ref));
	GITERR_CHECK_ALLOC(pkt);
	pkt->type = GIT_PKT_REF;

	if (git_tag_peel(&target, (git_tag *) obj) < 0)
		goto on_error;

	git_oid_cpy(&head->oid, git_object_id(target));
	git_object_free(obj);
	git_object_free(target);
	memcpy(&pkt->head, head, sizeof(git_remote_head));
	git__free(head);

	if (git_vector_insert(&transport->refs, pkt) < 0)
		return -1;

	return 0;

on_error:
	git_object_free(obj);
	git_object_free(target);
	return -1;
}
Esempio n. 2
0
static int _git_ssh_setup_conn(
	ssh_subtransport *t,
	const char *url,
	const char *cmd,
	git_smart_subtransport_stream **stream)
{
	char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
	const char *default_port="22";
	int auth_methods, error = 0;
	ssh_stream *s;
	git_cred *cred = NULL;
	LIBSSH2_SESSION* session=NULL;
	LIBSSH2_CHANNEL* channel=NULL;

	*stream = NULL;
	if (ssh_stream_alloc(t, url, cmd, stream) < 0)
		return -1;

	s = (ssh_stream *)*stream;

	if (!git__prefixcmp(url, prefix_ssh)) {
		if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0)
			goto on_error;
	} else {
		if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0)
			goto on_error;
		port = git__strdup(default_port);
		GITERR_CHECK_ALLOC(port);
	}

	/* we need the username to ask for auth methods */
	if (!user) {
		if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0)
			goto on_error;

		user = git__strdup(((git_cred_username *) cred)->username);
		cred->free(cred);
		cred = NULL;
		if (!user)
			goto on_error;
	} else if (user && pass) {
		if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0)
			goto on_error;
	}

	if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
		goto on_error;

	if ((error = _git_ssh_session_create(&session, s->socket)) < 0)
		goto on_error;

	if ((error = list_auth_methods(&auth_methods, session, user)) < 0)
		goto on_error;

	error = GIT_EAUTH;
	/* if we already have something to try */
	if (cred && auth_methods & cred->credtype)
		error = _git_ssh_authenticate_session(session, cred);

	while (error == GIT_EAUTH) {
		if (cred) {
			cred->free(cred);
			cred = NULL;
		}

		if ((error = request_creds(&cred, t, user, auth_methods)) < 0)
			goto on_error;

		if (strcmp(user, git_cred__username(cred))) {
			giterr_set(GITERR_SSH, "username does not match previous request");
			error = -1;
			goto on_error;
		}

		error = _git_ssh_authenticate_session(session, cred);
	}

	if (error < 0)
		goto on_error;

	channel = libssh2_channel_open_session(session);
	if (!channel) {
		error = -1;
		ssh_error(session, "Failed to open SSH channel");
		goto on_error;
	}

	libssh2_channel_set_blocking(channel, 1);

	s->session = session;
	s->channel = channel;

	t->current_stream = s;
	if (cred)
		cred->free(cred);

	git__free(host);
	git__free(port);
	git__free(path);
	git__free(user);
	git__free(pass);

	return 0;

on_error:
	s->session = NULL;
	s->channel = NULL;
	t->current_stream = NULL;

	if (*stream)
		ssh_stream_free(*stream);

	if (cred)
		cred->free(cred);

	git__free(host);
	git__free(port);
	git__free(user);
	git__free(pass);

	if (session)
		libssh2_session_free(session);

	return error;
}
Esempio n. 3
0
int git_reference__is_tag(const char *ref_name)
{
	return git__prefixcmp(ref_name, GIT_REFS_TAGS_DIR) == 0;
}
Esempio n. 4
0
int git_commit__parse(void *_commit, git_odb_object *odb_obj)
{
    git_commit *commit = _commit;
    const char *buffer_start = git_odb_object_data(odb_obj), *buffer;
    const char *buffer_end = buffer_start + git_odb_object_size(odb_obj);
    git_oid parent_id;
    size_t header_len;
    git_signature dummy_sig;

    buffer = buffer_start;

    /* Allocate for one, which will allow not to realloc 90% of the time  */
    git_array_init_to_size(commit->parent_ids, 1);
    GITERR_CHECK_ARRAY(commit->parent_ids);

    /* The tree is always the first field */
    if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
        goto bad_buffer;

    /*
     * TODO: commit grafts!
     */

    while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) {
        git_oid *new_id = git_array_alloc(commit->parent_ids);
        GITERR_CHECK_ALLOC(new_id);

        git_oid_cpy(new_id, &parent_id);
    }

    commit->author = git__malloc(sizeof(git_signature));
    GITERR_CHECK_ALLOC(commit->author);

    if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
        return -1;

    /* Some tools create multiple author fields, ignore the extra ones */
    while ((size_t)(buffer_end - buffer) >= strlen("author ") && !git__prefixcmp(buffer, "author ")) {
        if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0)
            return -1;

        git__free(dummy_sig.name);
        git__free(dummy_sig.email);
    }

    /* Always parse the committer; we need the commit time */
    commit->committer = git__malloc(sizeof(git_signature));
    GITERR_CHECK_ALLOC(commit->committer);

    if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
        return -1;

    /* Parse add'l header entries */
    while (buffer < buffer_end) {
        const char *eoln = buffer;
        if (buffer[-1] == '\n' && buffer[0] == '\n')
            break;

        while (eoln < buffer_end && *eoln != '\n')
            ++eoln;

        if (git__prefixcmp(buffer, "encoding ") == 0) {
            buffer += strlen("encoding ");

            commit->message_encoding = git__strndup(buffer, eoln - buffer);
            GITERR_CHECK_ALLOC(commit->message_encoding);
        }

        if (eoln < buffer_end && *eoln == '\n')
            ++eoln;
        buffer = eoln;
    }

    header_len = buffer - buffer_start;
    commit->raw_header = git__strndup(buffer_start, header_len);
    GITERR_CHECK_ALLOC(commit->raw_header);

    /* point "buffer" to data after header, +1 for the final LF */
    buffer = buffer_start + header_len + 1;

    /* extract commit message */
    if (buffer <= buffer_end) {
        commit->raw_message = git__strndup(buffer, buffer_end - buffer);
        GITERR_CHECK_ALLOC(commit->raw_message);
    }

    return 0;

bad_buffer:
    giterr_set(GITERR_OBJECT, "Failed to parse bad commit object");
    return -1;
}
Esempio n. 5
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. 6
0
static int _git_ssh_setup_conn(
	ssh_subtransport *t,
	const char *url,
	const char *cmd,
	git_smart_subtransport_stream **stream)
{
	char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
	const char *default_port="22";
	int auth_methods, error = 0;
	size_t i;
	ssh_stream *s;
	git_cred *cred = NULL;
	LIBSSH2_SESSION* session=NULL;
	LIBSSH2_CHANNEL* channel=NULL;

	t->current_stream = NULL;

	*stream = NULL;
	if (ssh_stream_alloc(t, url, cmd, stream) < 0)
		return -1;

	s = (ssh_stream *)*stream;
	s->session = NULL;
	s->channel = NULL;

	for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
		const char *p = ssh_prefixes[i];

		if (!git__prefixcmp(url, p)) {
			if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0)
				goto done;

			goto post_extract;
		}
	}
	if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0)
		goto done;
	port = git__strdup(default_port);
	GITERR_CHECK_ALLOC(port);

post_extract:
	if ((error = git_socket_stream_new(&s->io, host, port)) < 0 ||
	    (error = git_stream_connect(s->io)) < 0)
		goto done;

	if ((error = _git_ssh_session_create(&session, s->io)) < 0)
		goto done;

	if (t->owner->certificate_check_cb != NULL) {
		git_cert_hostkey cert = {{ 0 }}, *cert_ptr;
		const char *key;

		cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;

		key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
		if (key != NULL) {
			cert.type |= GIT_CERT_SSH_SHA1;
			memcpy(&cert.hash_sha1, key, 20);
		}

		key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
		if (key != NULL) {
			cert.type |= GIT_CERT_SSH_MD5;
			memcpy(&cert.hash_md5, key, 16);
		}

		if (cert.type == 0) {
			giterr_set(GITERR_SSH, "unable to get the host key");
			error = -1;
			goto done;
		}

		/* We don't currently trust any hostkeys */
		giterr_clear();

		cert_ptr = &cert;

		error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload);
		if (error < 0) {
			if (!giterr_last())
				giterr_set(GITERR_NET, "user cancelled hostkey check");

			goto done;
		}
	}

	/* we need the username to ask for auth methods */
	if (!user) {
		if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0)
			goto done;

		user = git__strdup(((git_cred_username *) cred)->username);
		cred->free(cred);
		cred = NULL;
		if (!user)
			goto done;
	} else if (user && pass) {
		if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0)
			goto done;
	}

	if ((error = list_auth_methods(&auth_methods, session, user)) < 0)
		goto done;

	error = GIT_EAUTH;
	/* if we already have something to try */
	if (cred && auth_methods & cred->credtype)
		error = _git_ssh_authenticate_session(session, cred);

	while (error == GIT_EAUTH) {
		if (cred) {
			cred->free(cred);
			cred = NULL;
		}

		if ((error = request_creds(&cred, t, user, auth_methods)) < 0)
			goto done;

		if (strcmp(user, git_cred__username(cred))) {
			giterr_set(GITERR_SSH, "username does not match previous request");
			error = -1;
			goto done;
		}

		error = _git_ssh_authenticate_session(session, cred);
	}

	if (error < 0)
		goto done;

	channel = libssh2_channel_open_session(session);
	if (!channel) {
		error = -1;
		ssh_error(session, "Failed to open SSH channel");
		goto done;
	}

	libssh2_channel_set_blocking(channel, 1);

	s->session = session;
	s->channel = channel;

	t->current_stream = s;

done:
	if (error < 0) {
		ssh_stream_free(*stream);

		if (session)
			libssh2_session_free(session);
	}

	if (cred)
		cred->free(cred);

	git__free(host);
	git__free(port);
	git__free(path);
	git__free(user);
	git__free(pass);

	return error;
}
Esempio n. 7
0
#include "vector.h"
#include "fileops.h"

BEGIN_TEST("refcnt", init_inc2_dec2_free)
	git_refcnt p;

	gitrc_init(&p, 0);
	gitrc_inc(&p);
	gitrc_inc(&p);
	must_be_true(!gitrc_dec(&p));
	must_be_true(gitrc_dec(&p));
	gitrc_free(&p);
END_TEST

BEGIN_TEST("strutil", prefix_comparison)
	must_be_true(git__prefixcmp("", "") == 0);
	must_be_true(git__prefixcmp("a", "") == 0);
	must_be_true(git__prefixcmp("", "a") < 0);
	must_be_true(git__prefixcmp("a", "b") < 0);
	must_be_true(git__prefixcmp("b", "a") > 0);
	must_be_true(git__prefixcmp("ab", "a") == 0);
	must_be_true(git__prefixcmp("ab", "ac") < 0);
	must_be_true(git__prefixcmp("ab", "aa") > 0);
END_TEST

BEGIN_TEST("strutil", suffix_comparison)
	must_be_true(git__suffixcmp("", "") == 0);
	must_be_true(git__suffixcmp("a", "") == 0);
	must_be_true(git__suffixcmp("", "a") < 0);
	must_be_true(git__suffixcmp("a", "b") < 0);
	must_be_true(git__suffixcmp("b", "a") > 0);
Esempio n. 8
0
File: ssh.c Progetto: Posnet/ctf3
static int _git_ssh_setup_conn(
	ssh_subtransport *t,
	const char *url,
	const char *cmd,
	git_smart_subtransport_stream **stream)
{
	char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
	const char *default_port="22";
	ssh_stream *s;
	LIBSSH2_SESSION* session=NULL;
	LIBSSH2_CHANNEL* channel=NULL;

	*stream = NULL;
	if (ssh_stream_alloc(t, url, cmd, stream) < 0)
		return -1;

	s = (ssh_stream *)*stream;

	if (!git__prefixcmp(url, prefix_ssh)) {
		if (gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port) < 0)
			goto on_error;
	} else {
		if (git_ssh_extract_url_parts(&host, &user, url) < 0)
			goto on_error;
		port = git__strdup(default_port);
		GITERR_CHECK_ALLOC(port);
	}

	if (gitno_connect(&s->socket, host, port, 0) < 0)
		goto on_error;

	if (user && pass) {
		if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0)
			goto on_error;
	} else if (t->owner->cred_acquire_cb) {
		if (t->owner->cred_acquire_cb(
				&t->cred, t->owner->url, user,
				GIT_CREDTYPE_USERPASS_PLAINTEXT |
				GIT_CREDTYPE_SSH_KEY |
				GIT_CREDTYPE_SSH_CUSTOM,
				t->owner->cred_acquire_payload) < 0)
			goto on_error;

		if (!t->cred) {
			giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials");
			goto on_error;
		}
	} else {
		giterr_set(GITERR_SSH, "Cannot set up SSH connection without credentials");
		goto on_error;
	}
	assert(t->cred);

	if (!user && !git_cred_has_username(t->cred)) {
		giterr_set_str(GITERR_NET, "Cannot authenticate without a username");
		goto on_error;
	}

	if (_git_ssh_session_create(&session, s->socket) < 0)
		goto on_error;

	if (_git_ssh_authenticate_session(session, user, t->cred) < 0)
		goto on_error;

	channel = libssh2_channel_open_session(session);
	if (!channel) {
		ssh_error(session, "Failed to open SSH channel");
		goto on_error;
	}

	libssh2_channel_set_blocking(channel, 1);

	s->session = session;
	s->channel = channel;

	t->current_stream = s;
	git__free(host);
	git__free(port);
	git__free(path);
	git__free(user);
	git__free(pass);

	return 0;

on_error:
	s->session = NULL;
	s->channel = NULL;
	t->current_stream = NULL;

	if (*stream)
		ssh_stream_free(*stream);

	git__free(host);
	git__free(port);
	git__free(user);
	git__free(pass);

	if (session)
		libssh2_session_free(session);

	return -1;
}
Esempio n. 9
0
static int _git_ssh_setup_tunnel(
	ssh_subtransport *t,
	const char *url,
	const char *gitCmd,
	git_smart_subtransport_stream **stream)
{
	char *host = NULL, *port = NULL, *path = NULL, *user = NULL, *pass = NULL;
	size_t i;
	ssh_stream *s;
	wchar_t *ssh = t->sshtoolpath;
	wchar_t *wideParams = NULL;
	wchar_t *cmd = NULL;
	git_buf params = GIT_BUF_INIT;
	int isPutty;
	size_t length;

	*stream = NULL;
	if (ssh_stream_alloc(t, url, gitCmd, stream) < 0) {
		giterr_set_oom();
		return -1;
	}

	s = (ssh_stream *)*stream;

	for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
		const char *p = ssh_prefixes[i];

		if (!git__prefixcmp(url, p)) {
			if (extract_url_parts(&host, &port, &path, &user, &pass, url, NULL) < 0)
				goto on_error;

			goto post_extract;
		}
	}
	if (git_ssh_extract_url_parts(&host, &user, url) < 0)
		goto on_error;

post_extract:
	if (!ssh)
	{
		giterr_set(GITERR_SSH, "No GIT_SSH tool configured");
		goto on_error;
	}

	isPutty = wcstristr(ssh, L"plink");
	if (port) {
		if (isPutty)
			git_buf_printf(&params, " -P %s", port);
		else
			git_buf_printf(&params, " -p %s", port);
	}
	if (isPutty && !wcstristr(ssh, L"tortoiseplink")) {
		git_buf_puts(&params, " -batch");
	}
	if (user)
		git_buf_printf(&params, " %s@%s ", user, host);
	else
		git_buf_printf(&params, " %s ", host);
	if (gen_proto(&params, s->cmd, s->url))
		goto on_error;
	if (git_buf_oom(&params)) {
		giterr_set_oom();
		goto on_error;
	}

	if (git__utf8_to_16_alloc(&wideParams, params.ptr) < 0) {
		giterr_set_oom();
		goto on_error;
	}
	git_buf_free(&params);

	length = wcslen(ssh) + wcslen(wideParams) + 3;
	cmd = git__calloc(length, sizeof(wchar_t));
	if (!cmd) {
		giterr_set_oom();
		goto on_error;
	}

	wcscat_s(cmd, length, L"\"");
	wcscat_s(cmd, length, ssh);
	wcscat_s(cmd, length, L"\"");
	wcscat_s(cmd, length, wideParams);

	if (command_start(cmd, &s->commandHandle, t->pEnv, isPutty ? CREATE_NEW_CONSOLE : DETACHED_PROCESS))
		goto on_error;

	git__free(wideParams);
	git__free(cmd);
	t->current_stream = s;
	git__free(host);
	git__free(port);
	git__free(path);
	git__free(user);
	git__free(pass);

	return 0;

on_error:
	t->current_stream = NULL;

	if (*stream)
		ssh_stream_free(*stream);

	git_buf_free(&params);

	if (wideParams)
		git__free(wideParams);

	if (cmd)
		git__free(cmd);

	git__free(host);
	git__free(port);
	git__free(user);
	git__free(pass);

	return -1;
}
Esempio n. 10
0
static int http_negotiate_fetch(git_transport *transport, git_repository *repo, const git_vector *wants)
{
	transport_http *t = (transport_http *) transport;
	int ret;
	unsigned int i;
	char buff[128];
	gitno_buffer buf;
	git_revwalk *walk = NULL;
	git_oid oid;
	git_pkt_ack *pkt;
	git_vector *common = &t->common;
	const char *prefix = "http://", *url = t->parent.url;
	git_buf request = GIT_BUF_INIT, data = GIT_BUF_INIT;
	gitno_buffer_setup(&buf, buff, sizeof(buff), t->socket);

	/* TODO: Store url in the transport */
	if (!git__prefixcmp(url, prefix))
		url += strlen(prefix);

	if (git_vector_init(common, 16, NULL) < 0)
		return -1;

	if (git_fetch_setup_walk(&walk, repo) < 0)
		return -1;

	do {
		if ((ret = do_connect(t, t->host, t->port)) < 0)
			goto cleanup;

		if ((ret = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0)
			goto cleanup;

		/* We need to send these on each connection */
		git_vector_foreach (common, i, pkt) {
			if ((ret = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
				goto cleanup;
		}

		i = 0;
		while ((i < 20) && ((ret = git_revwalk_next(&oid, walk)) == 0)) {
			if ((ret = git_pkt_buffer_have(&oid, &data)) < 0)
				goto cleanup;

			i++;
		}

		git_pkt_buffer_done(&data);

		if ((ret = gen_request(&request, url, t->host, "POST", "upload-pack", data.size, 0)) < 0)
			goto cleanup;

		if ((ret = gitno_send(t->socket, request.ptr, request.size, 0)) < 0)
			goto cleanup;

		if ((ret = gitno_send(t->socket, data.ptr, data.size, 0)) < 0)
			goto cleanup;

		git_buf_clear(&request);
		git_buf_clear(&data);

		if (ret < 0 || i >= 256)
			break;

		if ((ret = parse_response(t)) < 0)
			goto cleanup;

		if (t->pack_ready) {
			ret = 0;
			goto cleanup;
		}

	} while(1);

cleanup:
	git_buf_free(&request);
	git_buf_free(&data);
	git_revwalk_free(walk);
	return ret;
}
Esempio n. 11
0
static int add_ref(const char *name, git_repository *repo, git_vector *vec)
{
	const char peeled[] = "^{}";
	git_remote_head *head;
	git_reference *ref;
	git_object *obj = NULL;
	int error = GIT_SUCCESS, peel_len, ret;

	head = git__malloc(sizeof(git_remote_head));
	if (head == NULL)
		return GIT_ENOMEM;

	head->name = git__strdup(name);
	if (head->name == NULL) {
		error = GIT_ENOMEM;
		goto out;
	}

	error = git_reference_lookup(&ref, repo, name);
	if (error < GIT_SUCCESS)
		goto out;

	error = git_reference_resolve(&ref, ref);
	if (error < GIT_SUCCESS)
		goto out;

	git_oid_cpy(&head->oid, git_reference_oid(ref));

	error = git_vector_insert(vec, head);
	if (error < GIT_SUCCESS)
		goto out;

	/* If it's not a tag, we don't need to try to peel it */
	if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
		goto out;

	error = git_object_lookup(&obj, repo, &head->oid, GIT_OBJ_ANY);
	if (error < GIT_SUCCESS) {
		git__rethrow(error, "Failed to lookup object");
	}

	/* If it's not an annotated tag, just get out */
	if (git_object_type(obj) != GIT_OBJ_TAG)
		goto out;

	/* And if it's a tag, peel it, and add it to the list */
	head = git__malloc(sizeof(git_remote_head));
	peel_len = strlen(name) + STRLEN(peeled);
	head->name = git__malloc(peel_len + 1);
	ret = snprintf(head->name, peel_len + 1, "%s%s", name, peeled);
	if (ret >= peel_len + 1) {
		error = git__throw(GIT_ERROR, "The string is magically to long");
	}

	git_oid_cpy(&head->oid, git_tag_target_oid((git_tag *) obj));

	error = git_vector_insert(vec, head);
	if (error < GIT_SUCCESS)
		goto out;

 out:
	git_object_close(obj);
	if (error < GIT_SUCCESS) {
		free(head->name);
		free(head);
	}
	return error;
}
Esempio n. 12
0
static int http_action(
	git_smart_subtransport_stream **stream,
	git_smart_subtransport *subtransport,
	const char *url,
	git_smart_service_t action)
{
	http_subtransport *t = (http_subtransport *)subtransport;
	const char *default_port = NULL;
	int flags = 0, ret;

	if (!stream)
		return -1;

	if (!t->host || !t->port || !t->path) {
		if (!git__prefixcmp(url, prefix_http)) {
			url = url + strlen(prefix_http);
			default_port = "80";
		}

		if (!git__prefixcmp(url, prefix_https)) {
			url += strlen(prefix_https);
			default_port = "443";
			t->use_ssl = 1;
		}

		if (!default_port)
			return -1;

		if ((ret = gitno_extract_host_and_port(&t->host, &t->port,
				url, default_port)) < 0)
			return ret;

		t->path = strchr(url, '/');
	}

	if (!t->connected ||
		!http_should_keep_alive(&t->parser) ||
		!http_body_is_final(&t->parser)) {

		if (t->socket.socket)
			gitno_close(&t->socket);

		if (t->use_ssl) {
			int transport_flags;

			if (t->owner->parent.read_flags(&t->owner->parent, &transport_flags) < 0)
				return -1;

			flags |= GITNO_CONNECT_SSL;

			if (GIT_TRANSPORTFLAGS_NO_CHECK_CERT & transport_flags)
				flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT;
		}

		if (gitno_connect(&t->socket, t->host, t->port, flags) < 0)
			return -1;

		t->connected = 1;
	}

	switch (action)
	{
		case GIT_SERVICE_UPLOADPACK_LS:
			return http_uploadpack_ls(t, stream);

		case GIT_SERVICE_UPLOADPACK:
			return http_uploadpack(t, stream);

		case GIT_SERVICE_RECEIVEPACK_LS:
			return http_receivepack_ls(t, stream);

		case GIT_SERVICE_RECEIVEPACK:
			return http_receivepack(t, stream);
	}

	*stream = NULL;
	return -1;
}
Esempio n. 13
0
int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
{
	const char *buffer = data;
	const char *buffer_end = (const char *)data + len;
	git_oid parent_id;

	if (git_vector_init(&commit->parent_ids, 4, NULL) < 0)
		return -1;

	if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
		goto bad_buffer;

	/*
	 * TODO: commit grafts!
	 */

	while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) {
		git_oid *new_id = git__malloc(sizeof(git_oid));
		GITERR_CHECK_ALLOC(new_id);

		git_oid_cpy(new_id, &parent_id);

		if (git_vector_insert(&commit->parent_ids, new_id) < 0)
			return -1;
	}

	commit->author = git__malloc(sizeof(git_signature));
	GITERR_CHECK_ALLOC(commit->author);

	if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
		return -1;

	/* Always parse the committer; we need the commit time */
	commit->committer = git__malloc(sizeof(git_signature));
	GITERR_CHECK_ALLOC(commit->committer);

	if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
		return -1;

	/* Parse add'l header entries until blank line found */
	while (buffer < buffer_end && *buffer != '\n') {
		const char *eoln = buffer;
		while (eoln < buffer_end && *eoln != '\n')
			++eoln;

		if (git__prefixcmp(buffer, "encoding ") == 0) {
			buffer += strlen("encoding ");

			commit->message_encoding = git__strndup(buffer, eoln - buffer);
			GITERR_CHECK_ALLOC(commit->message_encoding);
		}

		if (eoln < buffer_end && *eoln == '\n')
			++eoln;

		buffer = eoln;
	}

	/* skip blank lines */
	while (buffer < buffer_end - 1 && *buffer == '\n')
		buffer++;

	/* parse commit message */
	if (buffer <= buffer_end) {
		commit->message = git__strndup(buffer, buffer_end - buffer);
		GITERR_CHECK_ALLOC(commit->message);
	}

	return 0;

bad_buffer:
	giterr_set(GITERR_OBJECT, "Failed to parse bad commit object");
	return -1;
}
Esempio n. 14
0
int git_pkt_parse_line(
	git_pkt **head, const char *line, const char **out, size_t bufflen)
{
	int ret;
	int32_t len;

	/* Not even enough for the length */
	if (bufflen > 0 && bufflen < PKT_LEN_SIZE)
		return GIT_EBUFS;

	len = parse_len(line);
	if (len < 0) {
		/*
		 * If we fail to parse the length, it might be because the
		 * server is trying to send us the packfile already.
		 */
		if (bufflen >= 4 && !git__prefixcmp(line, "PACK")) {
			giterr_clear();
			*out = line;
			return pack_pkt(head);
		}

		return (int)len;
	}

	/*
	 * If we were given a buffer length, then make sure there is
	 * enough in the buffer to satisfy this line
	 */
	if (bufflen > 0 && bufflen < (size_t)len)
		return GIT_EBUFS;

	line += PKT_LEN_SIZE;
	/*
	 * TODO: How do we deal with empty lines? Try again? with the next
	 * line?
	 */
	if (len == PKT_LEN_SIZE) {
		*out = line;
		return 0;
	}

	if (len == 0) { /* Flush pkt */
		*out = line;
		return flush_pkt(head);
	}

	len -= PKT_LEN_SIZE; /* the encoded length includes its own size */

	/* Assming the minimal size is actually 4 */
	if (!git__prefixcmp(line, "ACK"))
		ret = ack_pkt(head, line, len);
	else if (!git__prefixcmp(line, "NAK"))
		ret = nak_pkt(head);
	else if (!git__prefixcmp(line, "ERR "))
		ret = err_pkt(head, line, len);
	else if (*line == '#')
		ret = comment_pkt(head, line, len);
	else
		ret = ref_pkt(head, line, len);

	*out = line + len;

	return ret;
}
Esempio n. 15
0
int gitno_connection_data_from_url(
		gitno_connection_data *data,
		const char *url,
		const char *service_suffix)
{
	int error = -1;
	const char *default_port = NULL, *path_search_start = NULL;
	char *original_host = NULL;

	/* service_suffix is optional */
	assert(data && url);

	/* Save these for comparison later */
	original_host = data->host;
	data->host = NULL;
	gitno_connection_data_free_ptrs(data);

	if (!git__prefixcmp(url, prefix_http)) {
		path_search_start = url + strlen(prefix_http);
		default_port = "80";

		if (data->use_ssl) {
			giterr_set(GITERR_NET, "redirect from HTTPS to HTTP is not allowed");
			goto cleanup;
		}
	} else if (!git__prefixcmp(url, prefix_https)) {
		path_search_start = url + strlen(prefix_https);
		default_port = "443";
		data->use_ssl = true;
	} else if (url[0] == '/')
		default_port = data->use_ssl ? "443" : "80";

	if (!default_port) {
		giterr_set(GITERR_NET, "unrecognized URL prefix");
		goto cleanup;
	}

	error = gitno_extract_url_parts(
		&data->host, &data->port, &data->path, &data->user, &data->pass,
		url, default_port);

	if (url[0] == '/') {
		/* Relative redirect; reuse original host name and port */
		path_search_start = url;
		git__free(data->host);
		data->host = original_host;
		original_host = NULL;
	}

	if (!error) {
		const char *path = strchr(path_search_start, '/');
		size_t pathlen = strlen(path);
		size_t suffixlen = service_suffix ? strlen(service_suffix) : 0;

		if (suffixlen &&
		    !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) {
			git__free(data->path);
			data->path = git__strndup(path, pathlen - suffixlen);
		} else {
			git__free(data->path);
			data->path = git__strdup(path);
		}

		/* Check for errors in the resulting data */
		if (original_host && url[0] != '/' && strcmp(original_host, data->host)) {
			giterr_set(GITERR_NET, "cross host redirect not allowed");
			error = -1;
		}
	}

cleanup:
	if (original_host) git__free(original_host);
	return error;
}
Esempio n. 16
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;
	size_t i;
	const git_proxy_options *proxy_opts;

	/* 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;
	}

	proxy_opts = &t->owner->proxy;
	if (proxy_opts->type == GIT_PROXY_AUTO) {
		/* Set proxy if necessary */
		if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0)
			goto on_error;
	}
	else if (proxy_opts->type == GIT_PROXY_SPECIFIED) {
		proxy_url = git__strdup(proxy_opts->url);
		GITERR_CHECK_ALLOC(proxy_url);
	}

	if (proxy_url) {
		git_buf processed_url = GIT_BUF_INIT;
		WINHTTP_PROXY_INFO proxy_info;
		wchar_t *proxy_wide;

		if (!git__prefixcmp(proxy_url, SCHEME_HTTP)) {
			t->proxy_connection_data.use_ssl = false;
		} else if (!git__prefixcmp(proxy_url, SCHEME_HTTPS)) {
			t->proxy_connection_data.use_ssl = true;
		} else {
			giterr_set(GITERR_NET, "invalid URL: '%s'", proxy_url);
			return -1;
		}

		gitno_connection_data_free_ptrs(&t->proxy_connection_data);

		if ((error = gitno_extract_url_parts(&t->proxy_connection_data.host, &t->proxy_connection_data.port, NULL,
				&t->proxy_connection_data.user, &t->proxy_connection_data.pass, proxy_url, NULL)) < 0)
			goto on_error;

		if (t->proxy_connection_data.user && t->proxy_connection_data.pass) {
			if (t->proxy_cred) {
				t->proxy_cred->free(t->proxy_cred);
			}

			if ((error = git_cred_userpass_plaintext_new(&t->proxy_cred, t->proxy_connection_data.user, t->proxy_connection_data.pass)) < 0)
				goto on_error;
		}

		if (t->proxy_connection_data.use_ssl)
			git_buf_PUTS(&processed_url, SCHEME_HTTPS);
		else
			git_buf_PUTS(&processed_url, SCHEME_HTTP);

		git_buf_puts(&processed_url, t->proxy_connection_data.host);
		if (t->proxy_connection_data.port)
			git_buf_printf(&processed_url, ":%s", t->proxy_connection_data.port);

		if (git_buf_oom(&processed_url)) {
			giterr_set_oom();
			error = -1;
			goto on_error;
		}

		/* Convert URL to wide characters */
		error = git__utf8_to_16_alloc(&proxy_wide, processed_url.ptr);
		git_buf_free(&processed_url);
		if (error < 0)
			goto on_error;

		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);

		if (t->proxy_cred) {
			if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) {
				if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred)) < 0)
					goto on_error;
			}
		}

	}

	/* 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;
		}
	}

	for (i = 0; i < t->owner->custom_headers.count; i++) {
		if (t->owner->custom_headers.strings[i]) {
			git_buf_clear(&buf);
			git_buf_puts(&buf, t->owner->custom_headers.strings[i]);
			if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
				giterr_set(GITERR_OS, "failed to convert custom 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 &&
		apply_userpass_credential(s->request, t->auth_mechanisms, t->cred) < 0)
		goto on_error;
	else if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_DEFAULT &&
		apply_default_credentials(s->request, t->auth_mechanisms) < 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_userpass_credential(s->request, GIT_WINHTTP_AUTH_BASIC, 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. 17
0
static int treebuilder_filter_prefixed(
	const git_tree_entry *entry, void *payload)
{
	return !git__prefixcmp(git_tree_entry_name(entry), payload);
}
Esempio n. 18
0
File: path.c Progetto: evhan/libgit2
int git_path_walk_up(
    git_buf *path,
    const char *ceiling,
    int (*cb)(void *data, const char *),
    void *data)
{
    int error = 0;
    git_buf iter;
    ssize_t stop = 0, scan;
    char oldc = '\0';

    assert(path && cb);

    if (ceiling != NULL) {
        if (git__prefixcmp(path->ptr, ceiling) == 0)
            stop = (ssize_t)strlen(ceiling);
        else
            stop = git_buf_len(path);
    }
    scan = git_buf_len(path);

    /* empty path: yield only once */
    if (!scan) {
        error = cb(data, "");
        if (error)
            giterr_set_after_callback(error);
        return error;
    }

    iter.ptr = path->ptr;
    iter.size = git_buf_len(path);
    iter.asize = path->asize;

    while (scan >= stop) {
        error = cb(data, iter.ptr);
        iter.ptr[scan] = oldc;

        if (error) {
            giterr_set_after_callback(error);
            break;
        }

        scan = git_buf_rfind_next(&iter, '/');
        if (scan >= 0) {
            scan++;
            oldc = iter.ptr[scan];
            iter.size = scan;
            iter.ptr[scan] = '\0';
        }
    }

    if (scan >= 0)
        iter.ptr[scan] = oldc;

    /* relative path: yield for the last component */
    if (!error && stop == 0 && iter.ptr[0] != '/') {
        error = cb(data, "");
        if (error)
            giterr_set_after_callback(error);
    }

    return error;
}
Esempio n. 19
0
/**
 * Invoked 'callback' for each tag
 *
 * @param name The name of the tag
 * @param oid The id of the tag
 * @param payload Payload data passed to 'git_tag_foreach'
 * @return 0 on success, else error code
 */
static int git2r_tag_foreach_cb(const char *name, git_oid *oid, void *payload)
{
    int err = 0;
    git_object *object = NULL;
    git2r_tag_foreach_cb_data *cb_data = (git2r_tag_foreach_cb_data*)payload;

    /* Check if we have a list to populate */
    if (R_NilValue != cb_data->tags) {
        int skip = 0;
        SEXP item;

        err = git_object_lookup(&object, cb_data->repository, oid, GIT_OBJ_ANY);
        if (err)
            goto cleanup;

        switch (git_object_type(object)) {
        case GIT_OBJ_COMMIT:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_commit")));
            git2r_commit_init((git_commit*)object, cb_data->repo, item);
            break;
        case GIT_OBJ_TREE:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_tree")));
            git2r_tree_init((git_tree*)object, cb_data->repo, item);
            break;
        case GIT_OBJ_BLOB:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_blob")));
            git2r_blob_init((git_blob*)object, cb_data->repo, item);
            break;
        case GIT_OBJ_TAG:
            SET_VECTOR_ELT(
                cb_data->tags,
                cb_data->n,
                item = NEW_OBJECT(MAKE_CLASS("git_tag")));
            git2r_tag_init((git_tag*)object, cb_data->repo, item);
            break;
        default:
            git2r_error(__func__, NULL, git2r_err_object_type, NULL);
        }


        if (git__prefixcmp(name, "refs/tags/") == 0)
            skip = strlen("refs/tags/");
        SET_STRING_ELT(
            getAttrib(cb_data->tags, R_NamesSymbol),
            cb_data->n,
            mkChar(name + skip));

        if (object)
            git_object_free(object);
        object = NULL;
    }

    cb_data->n += 1;

cleanup:
    if (object)
        git_object_free(object);

    return err;
}
Esempio n. 20
0
static int addall_match_prefix(
	const char *path, const char *matched_pathspec, void *payload)
{
	GIT_UNUSED(matched_pathspec);
	return !git__prefixcmp(path, payload) ? 0 : 1;
}
Esempio n. 21
0
static int fetchhead_ref_parse(
	git_oid *oid,
	unsigned int *is_merge,
	git_buf *ref_name,
	const char **remote_url,
	char *line,
	size_t line_num)
{
	char *oid_str, *is_merge_str, *desc, *name = NULL;
	const char *type = NULL;
	int error = 0;

	*remote_url = NULL;

	if (!*line) {
		giterr_set(GITERR_FETCHHEAD,
			"Empty line in FETCH_HEAD line %"PRIuZ, line_num);
		return -1;
	}

	/* Compat with old git clients that wrote FETCH_HEAD like a loose ref. */
	if ((oid_str = git__strsep(&line, "\t")) == NULL) {
		oid_str = line;
		line += strlen(line);

		*is_merge = 1;
	}

	if (strlen(oid_str) != GIT_OID_HEXSZ) {
		giterr_set(GITERR_FETCHHEAD,
			"Invalid object ID in FETCH_HEAD line %"PRIuZ, line_num);
		return -1;
	}

	if (git_oid_fromstr(oid, oid_str) < 0) {
		const git_error *oid_err = giterr_last();
		const char *err_msg = oid_err ? oid_err->message : "Invalid object ID";

		giterr_set(GITERR_FETCHHEAD, "%s in FETCH_HEAD line %"PRIuZ,
			err_msg, line_num);
		return -1;
	}

	/* Parse new data from newer git clients */
	if (*line) {
		if ((is_merge_str = git__strsep(&line, "\t")) == NULL) {
			giterr_set(GITERR_FETCHHEAD,
				"Invalid description data in FETCH_HEAD line %"PRIuZ, line_num);
			return -1;
		}

		if (*is_merge_str == '\0')
			*is_merge = 1;
		else if (strcmp(is_merge_str, "not-for-merge") == 0)
			*is_merge = 0;
		else {
			giterr_set(GITERR_FETCHHEAD,
				"Invalid for-merge entry in FETCH_HEAD line %"PRIuZ, line_num);
			return -1;
		}

		if ((desc = line) == NULL) {
			giterr_set(GITERR_FETCHHEAD,
				"Invalid description in FETCH_HEAD line %"PRIuZ, line_num);
			return -1;
		}

		if (git__prefixcmp(desc, "branch '") == 0) {
			type = GIT_REFS_HEADS_DIR;
			name = desc + 8;
		} else if (git__prefixcmp(desc, "tag '") == 0) {
			type = GIT_REFS_TAGS_DIR;
			name = desc + 5;
		} else if (git__prefixcmp(desc, "'") == 0)
			name = desc + 1;

		if (name) {
			if ((desc = strstr(name, "' ")) == NULL ||
				git__prefixcmp(desc, "' of ") != 0) {
				giterr_set(GITERR_FETCHHEAD,
					"Invalid description in FETCH_HEAD line %"PRIuZ, line_num);
				return -1;
			}

			*desc = '\0';
			desc += 5;
		}

		*remote_url = desc;
	}

	git_buf_clear(ref_name);

	if (type)
		git_buf_join(ref_name, '/', type, name);
	else if(name)
		git_buf_puts(ref_name, name);

	return error;
}
Esempio n. 22
0
int git_reference__is_branch(const char *ref_name)
{
	return git__prefixcmp(ref_name, GIT_REFS_HEADS_DIR) == 0;
}
Esempio n. 23
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;
	git_refspec *cur;

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

	assert(out && spec && refs);

	cur = git__calloc(1, sizeof(git_refspec));
	GIT_ERROR_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);
			git_buf_printf(&buf, formatters[j], spec->src);
			GIT_ERROR_CHECK_ALLOC_BUF(&buf);

			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);
		GIT_ERROR_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);
		}

		git_buf_puts(&buf, spec->dst);
		GIT_ERROR_CHECK_ALLOC_BUF(&buf);

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

	git_buf_dispose(&buf);

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

	return git_vector_insert(out, cur);
}
Esempio n. 24
0
int git_reference__is_note(const char *ref_name)
{
	return git__prefixcmp(ref_name, GIT_REFS_NOTES_DIR) == 0;
}
Esempio n. 25
0
int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
{
	const char *buffer = data;
	const char *buffer_end = (const char *)data + len;

	git_oid parent_oid;
	int error;

	git_vector_init(&commit->parent_oids, 4, NULL);

	if ((error = git_oid__parse(&commit->tree_oid, &buffer, buffer_end, "tree ")) < GIT_SUCCESS)
		return git__rethrow(error, "Failed to parse buffer");

	/*
	 * TODO: commit grafts!
	 */

	while (git_oid__parse(&parent_oid, &buffer, buffer_end, "parent ") == GIT_SUCCESS) {
		git_oid *new_oid;

		new_oid = git__malloc(sizeof(git_oid));
		git_oid_cpy(new_oid, &parent_oid);

		if (git_vector_insert(&commit->parent_oids, new_oid) < GIT_SUCCESS)
			return GIT_ENOMEM;
	}

	commit->author = git__malloc(sizeof(git_signature));
	if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n')) < GIT_SUCCESS)
		return git__rethrow(error, "Failed to parse commit");

	/* Always parse the committer; we need the commit time */
	commit->committer = git__malloc(sizeof(git_signature));
	if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n')) < GIT_SUCCESS)
		return git__rethrow(error, "Failed to parse commit");

	if (git__prefixcmp(buffer, "encoding ") == 0) {
		const char *encoding_end;
		buffer += strlen("encoding ");

		encoding_end = buffer;
		while (encoding_end < buffer_end && *encoding_end != '\n')
			encoding_end++;

		commit->message_encoding = git__strndup(buffer, encoding_end - buffer);
		if (!commit->message_encoding)
			return GIT_ENOMEM;

		buffer = encoding_end;
	}

	/* parse commit message */
	while (buffer < buffer_end && *buffer == '\n')
		buffer++;

	if (buffer < buffer_end) {
		commit->message = git__strndup(buffer, buffer_end - buffer);
		if (!commit->message)
			return GIT_ENOMEM;
	}

	return GIT_SUCCESS;
}
Esempio n. 26
0
int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field)
{
    git_odb_object *obj;
    git_odb *odb;
    const char *buf;
    const char *h, *eol;
    int error;

    git_buf_sanitize(signature);
    git_buf_sanitize(signed_data);

    if (!field)
        field = "gpgsig";

    if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
        return error;

    if ((error = git_odb_read(&obj, odb, commit_id)) < 0)
        return error;

    if (obj->cached.type != GIT_OBJ_COMMIT) {
        giterr_set(GITERR_INVALID, "the requested type does not match the type in ODB");
        error = GIT_ENOTFOUND;
        goto cleanup;
    }

    buf = git_odb_object_data(obj);

    while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
        h++;
        if (git__prefixcmp(buf, field)) {
            if (git_buf_put(signed_data, buf, h - buf) < 0)
                return -1;

            buf = h;
            continue;
        }

        h = buf;
        h += strlen(field);
        eol = strchr(h, '\n');
        if (h[0] != ' ') {
            buf = h;
            continue;
        }
        if (!eol)
            goto malformed;

        h++; /* skip the SP */

        git_buf_put(signature, h, eol - h);
        if (git_buf_oom(signature))
            goto oom;

        /* If the next line starts with SP, it's multi-line, we must continue */
        while (eol[1] == ' ') {
            git_buf_putc(signature, '\n');
            h = eol + 2;
            eol = strchr(h, '\n');
            if (!eol)
                goto malformed;

            git_buf_put(signature, h, eol - h);
        }

        if (git_buf_oom(signature))
            goto oom;

        git_odb_object_free(obj);
        return git_buf_puts(signed_data, eol+1);
    }

    giterr_set(GITERR_OBJECT, "this commit is not signed");
    error = GIT_ENOTFOUND;
    goto cleanup;

malformed:
    giterr_set(GITERR_OBJECT, "malformed header");
    error = -1;
    goto cleanup;
oom:
    giterr_set_oom();
    error = -1;
    goto cleanup;

cleanup:
    git_odb_object_free(obj);
    git_buf_clear(signature);
    git_buf_clear(signed_data);
    return error;
}
Esempio n. 27
0
static int _git_ssh_setup_conn(
	ssh_subtransport *t,
	const char *url,
	const char *cmd,
	git_smart_subtransport_stream **stream
)
{
	char *host, *port=NULL, *user=NULL, *pass=NULL;
	const char *default_port="22";
	ssh_stream *s;
	LIBSSH2_SESSION* session=NULL;
	LIBSSH2_CHANNEL* channel=NULL;
	
	*stream = NULL;
	if (ssh_stream_alloc(t, url, cmd, stream) < 0)
		return -1;
	
	s = (ssh_stream *)*stream;
	
	if (!git__prefixcmp(url, prefix_ssh)) {
		url = url + strlen(prefix_ssh);
		if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0)
			goto on_error;
	} else {
		if (git_ssh_extract_url_parts(&host, &user, url) < 0)
			goto on_error;
		port = git__strdup(default_port);
		GITERR_CHECK_ALLOC(port);
	}
	
	if (gitno_connect(&s->socket, host, port, 0) < 0)
		goto on_error;
	
	if (user && pass) {
		if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0)
			goto on_error;
	} else {
		if (t->owner->cred_acquire_cb(&t->cred,
				t->owner->url,
				user,
				GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE | GIT_CREDTYPE_SSH_PUBLICKEY,
				t->owner->cred_acquire_payload) < 0)
			return -1;
	}
	assert(t->cred);
	
	if (!user) {
		user = git__strdup(default_user);
	}
	
	if (_git_ssh_session_create(&session, s->socket) < 0)
		goto on_error;
	
    if (_git_ssh_authenticate_session(session, user, t->cred) < 0)
		goto on_error;
	
	channel = libssh2_channel_open_session(session);
	if (!channel)
        goto on_error;
	
	libssh2_channel_set_blocking(channel, 1);
	
	s->session = session;
	s->channel = channel;
	
	t->current_stream = s;
	git__free(host);
	git__free(port);
	git__free(user);
	git__free(pass);

	return 0;
	
on_error:
	if (*stream)
		ssh_stream_free(*stream);
	
	git__free(host);
	git__free(port);
	git__free(user);
	git__free(pass);

	if (session)
		libssh2_session_free(session), session = NULL;

	return -1;
}