Exemple #1
0
void test_commit_parse__header(void)
{
   git_oid oid;

   parse_test_case *testcase;
   for (testcase = passing_header_cases; testcase->line != NULL; testcase++)
   {
      const char *line = testcase->line;
      const char *line_end = line + strlen(line);

      cl_git_pass(git_oid__parse(&oid, &line, line_end, testcase->header));
      cl_assert(line == line_end);
   }

   for (testcase = failing_header_cases; testcase->line != NULL; testcase++)
   {
      const char *line = testcase->line;
      const char *line_end = line + strlen(line);

      cl_git_fail(git_oid__parse(&oid, &line, line_end, testcase->header));
   }
}
Exemple #2
0
int git_commit__parse_raw(void *_commit, const char *data, size_t size)
{
	git_commit *commit = _commit;
	const char *buffer_start = data, *buffer;
	const char *buffer_end = buffer_start + size;
	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 (!git__prefixncmp(buffer, buffer_end - 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__prefixncmp(buffer, buffer_end - 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);
	else
		commit->raw_message = git__strdup("");
	GITERR_CHECK_ALLOC(commit->raw_message);

	return 0;

bad_buffer:
	giterr_set(GITERR_OBJECT, "failed to parse bad commit object");
	return -1;
}
Exemple #3
0
static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
{
    static const char *tag_types[] = {
        NULL, "commit\n", "tree\n", "blob\n", "tag\n"
    };

    unsigned int i;
    size_t text_len, alloc_len;
    char *search;

    if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
        return tag_error("Object field invalid");

    if (buffer + 5 >= buffer_end)
        return tag_error("Object too short");

    if (memcmp(buffer, "type ", 5) != 0)
        return tag_error("Type field not found");
    buffer += 5;

    tag->type = GIT_OBJ_BAD;

    for (i = 1; i < ARRAY_SIZE(tag_types); ++i) {
        size_t type_length = strlen(tag_types[i]);

        if (buffer + type_length >= buffer_end)
            return tag_error("Object too short");

        if (memcmp(buffer, tag_types[i], type_length) == 0) {
            tag->type = i;
            buffer += type_length;
            break;
        }
    }

    if (tag->type == GIT_OBJ_BAD)
        return tag_error("Invalid object type");

    if (buffer + 4 >= buffer_end)
        return tag_error("Object too short");

    if (memcmp(buffer, "tag ", 4) != 0)
        return tag_error("Tag field not found");

    buffer += 4;

    search = memchr(buffer, '\n', buffer_end - buffer);
    if (search == NULL)
        return tag_error("Object too short");

    text_len = search - buffer;

    GITERR_CHECK_ALLOC_ADD(&alloc_len, text_len, 1);
    tag->tag_name = git__malloc(alloc_len);
    GITERR_CHECK_ALLOC(tag->tag_name);

    memcpy(tag->tag_name, buffer, text_len);
    tag->tag_name[text_len] = '\0';

    buffer = search + 1;

    tag->tagger = NULL;
    if (buffer < buffer_end && *buffer != '\n') {
        tag->tagger = git__malloc(sizeof(git_signature));
        GITERR_CHECK_ALLOC(tag->tagger);

        if (git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ", '\n') < 0)
            return -1;
    }

    tag->message = NULL;
    if (buffer < buffer_end) {
        if( *buffer != '\n' )
            return tag_error("No new line before message");

        text_len = buffer_end - ++buffer;

        GITERR_CHECK_ALLOC_ADD(&alloc_len, text_len, 1);
        tag->message = git__malloc(alloc_len);
        GITERR_CHECK_ALLOC(tag->message);

        memcpy(tag->message, buffer, text_len);
        tag->message[text_len] = '\0';
    }

    return 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;
}
Exemple #5
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;
}