Beispiel #1
0
int git_pkt_buffer_wants(const git_vector *refs, git_transport_caps *caps, git_buf *buf)
{
	unsigned int i = 0;
	git_remote_head *head;

	if (caps->common) {
		for (; i < refs->length; ++i) {
			head = refs->contents[i];
			if (!head->local)
				break;
		}

		if (buffer_want_with_caps(refs->contents[i], caps, buf) < 0)
			return -1;

		i++;
	}

	for (; i < refs->length; ++i) {
		char oid[GIT_OID_HEXSZ];

		head = refs->contents[i];
		if (head->local)
			continue;

		git_oid_fmt(oid, &head->oid);
		git_buf_put(buf, pkt_want_prefix, strlen(pkt_want_prefix));
		git_buf_put(buf, oid, GIT_OID_HEXSZ);
		git_buf_putc(buf, '\n');
		if (git_buf_oom(buf))
			return -1;
	}

	return git_pkt_buffer_flush(buf);
}
Beispiel #2
0
int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld)
{
	unsigned int i;
	int error;
	git_buf tree = GIT_BUF_INIT;

	assert(bld);

	sort_entries(bld);

	/* Grow the buffer beforehand to an estimated size */
	git_buf_grow(&tree, bld->entries.length * 72);

	for (i = 0; i < bld->entries.length; ++i) {
		git_tree_entry *entry = bld->entries.contents[i];

		if (entry->removed)
			continue;

		git_buf_printf(&tree, "%o ", entry->attr);
		git_buf_put(&tree, entry->filename, entry->filename_len + 1);
		git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
	}

	if (git_buf_oom(&tree)) {
		git_buf_free(&tree);
		return git__throw(GIT_ENOMEM, "Not enough memory to build the tree data");
	}

	error = git_odb_write(oid, git_repository_database(repo), tree.ptr, tree.size, GIT_OBJ_TREE);
	git_buf_free(&tree);

	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write tree");
}
Beispiel #3
0
static int ident_insert_id(
	git_buf *to, const git_buf *from, const git_filter_source *src)
{
	char oid[GIT_OID_HEXSZ+1];
	const char *id_start, *id_end, *from_end = from->ptr + from->size;
	size_t need_size;

	/* replace $Id$ with blob id */

	if (!git_filter_source_id(src))
		return GIT_PASSTHROUGH;

	git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src));

	if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
		return GIT_PASSTHROUGH;

	need_size = (size_t)(id_start - from->ptr) +
		5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ +
		(size_t)(from_end - id_end);

	if (git_buf_grow(to, need_size) < 0)
		return -1;

	git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
	git_buf_put(to, "$Id: ", 5);
	git_buf_put(to, oid, GIT_OID_HEXSZ);
	git_buf_putc(to, '$');
	git_buf_put(to, id_end, (size_t)(from_end - id_end));

	return git_buf_oom(to) ? -1 : 0;
}
Beispiel #4
0
static int refspec_transform(
	git_buf *out, const char *from, const char *to, const char *name)
{
	const char *from_star, *to_star;
	size_t replacement_len, star_offset;

	git_buf_sanitize(out);
	git_buf_clear(out);

	/*
	 * There are two parts to each side of a refspec, the bit
	 * before the star and the bit after it. The star can be in
	 * the middle of the pattern, so we need to look at each bit
	 * individually.
	 */
	from_star = strchr(from, '*');
	to_star = strchr(to, '*');

	assert(from_star && to_star);

	/* star offset, both in 'from' and in 'name' */
	star_offset = from_star - from;

	/* the first half is copied over */
	git_buf_put(out, to, to_star - to);

	/*
	 * Copy over the name, but exclude the trailing part in "from" starting
	 * after the glob
	 */
	replacement_len = strlen(name + star_offset) - strlen(from_star + 1);
	git_buf_put(out, name + star_offset, replacement_len);

	return git_buf_puts(out, to_star + 1);
}
Beispiel #5
0
int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
{
	const char *eol, *buf = commit->raw_header;

	git_buf_clear(out);

	while ((eol = strchr(buf, '\n'))) {
		/* We can skip continuations here */
		if (buf[0] == ' ') {
			buf = eol + 1;
			continue;
		}

		/* Skip until we find the field we're after */
		if (git__prefixcmp(buf, field)) {
			buf = eol + 1;
			continue;
		}

		buf += strlen(field);
		/* Check that we're not matching a prefix but the field itself */
		if (buf[0] != ' ') {
			buf = eol + 1;
			continue;
		}

		buf++; /* skip the SP */

		git_buf_put(out, buf, eol - buf);
		if (git_buf_oom(out))
			goto oom;

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

			git_buf_put(out, buf, eol - buf);
		}

		if (git_buf_oom(out))
			goto oom;

		return 0;
	}

	giterr_set(GITERR_OBJECT, "no such field '%s'", field);
	return GIT_ENOTFOUND;

malformed:
	giterr_set(GITERR_OBJECT, "malformed header");
	return -1;
oom:
	giterr_set_oom();
	return -1;
}
Beispiel #6
0
int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
{
	const char *buf = commit->raw_header;
	const char *h, *eol;

	git_buf_sanitize(out);
	while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
		h++;
		if (git__prefixcmp(h, field)) {
			buf = h;
			continue;
		}

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

		h++; /* skip the SP */

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

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

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

		if (git_buf_oom(out))
			goto oom;

		return 0;
	}

	return GIT_ENOTFOUND;

malformed:
	giterr_set(GITERR_OBJECT, "malformed header");
	return -1;
oom:
	giterr_set_oom();
	return -1;
}
Beispiel #7
0
static int prepare_worktree_commit_message(
	git_buf* msg,
	const char *user_message)
{
	git_buf buf = GIT_BUF_INIT;
	int error;

	if ((error = git_buf_set(&buf, git_buf_cstr(msg), git_buf_len(msg))) < 0)
		return error;

	git_buf_clear(msg);

	if (!user_message)
		git_buf_printf(msg, "WIP on %s", git_buf_cstr(&buf));
	else {
		const char *colon;

		if ((colon = strchr(git_buf_cstr(&buf), ':')) == NULL)
			goto cleanup;

		git_buf_puts(msg, "On ");
		git_buf_put(msg, git_buf_cstr(&buf), colon - buf.ptr);
		git_buf_printf(msg, ": %s\n", user_message);
	}

	error = (git_buf_oom(msg) || git_buf_oom(&buf)) ? -1 : 0;

cleanup:
	git_buf_free(&buf);

	return error;
}
Beispiel #8
0
int git_futils_cleanupdir_r(const char *path)
{
	int error;
	git_buf fullpath = GIT_BUF_INIT;
	futils__rmdir_data data;

	if ((error = git_buf_put(&fullpath, path, strlen(path))) < 0)
		goto clean_up;

	data.base    = "";
	data.baselen = 0;
	data.flags   = GIT_RMDIR_REMOVE_FILES;
	data.error   = 0;

	if (!git_path_exists(path)) {
		giterr_set(GITERR_OS, "Path does not exist: %s" , path);
		error = GIT_ERROR;
		goto clean_up;
	}

	if (!git_path_isdir(path)) {
		giterr_set(GITERR_OS, "Path is not a directory: %s" , path);
		error = GIT_ERROR;
		goto clean_up;
	}

	error = git_path_direach(&fullpath, futils__rmdir_recurs_foreach, &data);
	if (error == GIT_EUSER)
		error = data.error;

clean_up:
	git_buf_free(&fullpath);
	return error;
}
Beispiel #9
0
const char *git_commit_summary(git_commit *commit)
{
	git_buf summary = GIT_BUF_INIT;
	const char *msg, *space;

	assert(commit);

	if (!commit->summary) {
		for (msg = git_commit_message(commit), space = NULL; *msg; ++msg) {
			if (msg[0] == '\n' && (!msg[1] || msg[1] == '\n'))
				break;
			else if (msg[0] == '\n')
				git_buf_putc(&summary, ' ');
			else if (git__isspace(msg[0]))
				space = space ? space : msg;
			else if (space) {
				git_buf_put(&summary, space, (msg - space) + 1);
				space = NULL;
			} else
				git_buf_putc(&summary, *msg);
		}

		commit->summary = git_buf_detach(&summary);
		if (!commit->summary)
			commit->summary = git__strdup("");
	}

	return commit->summary;
}
Beispiel #10
0
/*
 * Create a git protocol request.
 *
 * For example: 0035git-upload-pack /libgit2/libgit2\0host=github.com\0
 */
static int gen_proto(git_buf *request, const char *cmd, const char *url)
{
	char *delim, *repo;
	char host[] = "host=";
	size_t len;

	delim = strchr(url, '/');
	if (delim == NULL) {
		giterr_set(GITERR_NET, "Malformed URL");
		return -1;
	}

	repo = delim;

	delim = strchr(url, ':');
	if (delim == NULL)
		delim = strchr(url, '/');

	len = 4 + strlen(cmd) + 1 + strlen(repo) + 1 + strlen(host) + (delim - url) + 1;

	git_buf_grow(request, len);
	git_buf_printf(request, "%04x%s %s%c%s",
		(unsigned int)(len & 0x0FFFF), cmd, repo, 0, host);
	git_buf_put(request, url, delim - url);
	git_buf_putc(request, '\0');

	if (git_buf_oom(request))
		return -1;

	return 0;
}
Beispiel #11
0
static int refspec_transform(
	git_buf *out, const char *from, const char *to, const char *name)
{
	size_t to_len   = to   ? strlen(to)   : 0;
	size_t from_len = from ? strlen(from) : 0;
	size_t name_len = name ? strlen(name) : 0;

	git_buf_sanitize(out);

	if (git_buf_set(out, to, to_len) < 0)
		return -1;

	if (to_len > 0) {
		/* No '*' at the end of 'to' means that refspec is mapped to one
		 * specific branch, so no actual transformation is needed.
		 */
		if (out->ptr[to_len - 1] != '*')
			return 0;
		git_buf_shorten(out, 1); /* remove trailing '*' copied from 'to' */
	}

	if (from_len > 0) /* ignore trailing '*' from 'from' */
		from_len--;
	if (from_len > name_len)
		from_len = name_len;

	return git_buf_put(out, name + from_len, name_len - from_len);
}
Beispiel #12
0
void test_clone_nonetwork__do_not_clean_existing_directory(void)
{
	git_buf path_buf = GIT_BUF_INIT;

	git_buf_put(&path_buf, "./foo", 5);

	/* Clone should not remove the directory if it already exists, but
	 * Should clean up entries it creates. */
	p_mkdir("./foo", GIT_DIR_MODE);
	cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options));
	cl_assert(git_path_exists("./foo"));

	/* Make sure the directory is empty. */
	cl_git_pass(git_path_direach(&path_buf,
		dont_call_me,
		NULL));

	/* Try again with a bare repository. */
	g_options.bare = true;
	cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options));
	cl_assert(git_path_exists("./foo"));

	/* Make sure the directory is empty. */
	cl_git_pass(git_path_direach(&path_buf,
		dont_call_me,
		NULL));

	git_buf_free(&path_buf);
}
Beispiel #13
0
void test_repo_init__at_filesystem_root(void)
{
	git_repository *repo;
	const char *sandbox = clar_sandbox_path();
	git_buf root = GIT_BUF_INIT;
	int root_len;

	if (!cl_is_env_set("GITTEST_INVASIVE_FS_STRUCTURE"))
		cl_skip();

	root_len = git_path_root(sandbox);
	cl_assert(root_len >= 0);

	git_buf_put(&root, sandbox, root_len+1);
	git_buf_joinpath(&root, root.ptr, "libgit2_test_dir");

	cl_assert(!git_path_exists(root.ptr));

	cl_git_pass(git_repository_init(&repo, root.ptr, 0));
	cl_assert(git_path_isdir(root.ptr));
	cl_git_pass(git_futils_rmdir_r(root.ptr, NULL, GIT_RMDIR_REMOVE_FILES));

	git_buf_free(&root);
	git_repository_free(repo);
}
Beispiel #14
0
static int on_header_field(http_parser *parser, const char *str, size_t len)
{
	transport_http *t = (transport_http *) parser->data;
	git_buf *buf = &t->buf;

	if (t->last_cb == VALUE && t->ct_found) {
		t->ct_finished = 1;
		t->ct_found = 0;
		t->content_type = git__strdup(git_buf_cstr(buf));
		GITERR_CHECK_ALLOC(t->content_type);
		git_buf_clear(buf);
	}

	if (t->ct_found) {
		t->last_cb = FIELD;
		return 0;
	}

	if (t->last_cb != FIELD)
		git_buf_clear(buf);

	git_buf_put(buf, str, len);
	t->last_cb = FIELD;

	return git_buf_oom(buf);
}
Beispiel #15
0
static int ensure_base_rev_loaded(git_object **object, git_reference **reference, const char *spec, size_t identifier_len, git_repository *repo, bool allow_empty_identifier)
{
	int error;
	git_buf identifier = GIT_BUF_INIT;

	if (*object != NULL)
		return 0;

	if (*reference != NULL) {
		if ((error = object_from_reference(object, *reference)) < 0)
			return error;

		git_reference_free(*reference);
		*reference = NULL;
		return 0;
	}

	if (!allow_empty_identifier && identifier_len == 0)
		return revspec_error(spec);

	if (git_buf_put(&identifier, spec, identifier_len) < 0)
		return -1;

	error = revparse_lookup_object(object, repo, git_buf_cstr(&identifier));
	git_buf_free(&identifier);

	return error;
}
Beispiel #16
0
static int print_cb(
	const git_diff_delta *delta,
	const git_diff_hunk *hunk,
	const git_diff_line *line,
	void *payload)
{
	git_buf *buf = (git_buf *)payload;

	GIT_UNUSED(delta);

	if (hunk)
		git_buf_put(buf, hunk->header, hunk->header_len);

	if (line)
		git_buf_put(buf, line->content, line->content_len);

	return git_buf_oom(buf) ? -1 : 0;
}
Beispiel #17
0
static int on_body_parse_response(http_parser *parser, const char *str, size_t len)
{
	transport_http *t = (transport_http *) parser->data;
	git_buf *buf = &t->buf;
	git_vector *common = &t->common;
	int error;
	const char *line_end, *ptr;

	if (len == 0) { /* EOF */
		if (git_buf_len(buf) != 0) {
			giterr_set(GITERR_NET, "Unexpected EOF");
			return t->error = -1;
		} else {
			return 0;
		}
	}

	git_buf_put(buf, str, len);
	ptr = buf->ptr;
	while (1) {
		git_pkt *pkt;

		if (git_buf_len(buf) == 0)
			return 0;

		error = git_pkt_parse_line(&pkt, ptr, &line_end, git_buf_len(buf));
		if (error == GIT_EBUFS) {
			return 0; /* Ask for more */
		}
		if (error < 0)
			return t->error = -1;

		git_buf_consume(buf, line_end);

		if (pkt->type == GIT_PKT_PACK) {
			git__free(pkt);
			t->pack_ready = 1;
			return 0;
		}

		if (pkt->type == GIT_PKT_NAK) {
			git__free(pkt);
			return 0;
		}

		if (pkt->type != GIT_PKT_ACK) {
			git__free(pkt);
			continue;
		}

		if (git_vector_insert(common, pkt) < 0)
			return -1;
	}

	return error;

}
Beispiel #18
0
static int on_body_store_refs(http_parser *parser, const char *str, size_t len)
{
	transport_http *t = (transport_http *) parser->data;

	if (parser->status_code == 404) {
		return git_buf_put(&t->buf, str, len);
	}

	return git_protocol_store_refs(&t->proto, str, len);
}
Beispiel #19
0
static int refspec_transform(
	git_buf *out, const char *from, const char *to, const char *name)
{
	const char *from_star, *to_star;
	const char *name_slash, *from_slash;
	size_t replacement_len, star_offset;

	git_buf_sanitize(out);
	git_buf_clear(out);

	/*
	 * There are two parts to each side of a refspec, the bit
	 * before the star and the bit after it. The star can be in
	 * the middle of the pattern, so we need to look at each bit
	 * individually.
	 */
	from_star = strchr(from, '*');
	to_star = strchr(to, '*');

	assert(from_star && to_star);

	/* star offset, both in 'from' and in 'name' */
	star_offset = from_star - from;

	/* the first half is copied over */
	git_buf_put(out, to, to_star - to);

	/* then we copy over the replacement, from the star's offset to the next slash in 'name' */
	name_slash = strchr(name + star_offset, '/');
	if (!name_slash)
		name_slash = strrchr(name, '\0');

	/* if there is no slash after the star in 'from', we want to copy everything over */
	from_slash = strchr(from + star_offset, '/');
	if (!from_slash)
		name_slash = strrchr(name, '\0');

	replacement_len = (name_slash - name) - star_offset;
	git_buf_put(out, name + star_offset, replacement_len);

	return git_buf_puts(out, to_star + 1);
}
Beispiel #20
0
static int command_readall(HANDLE handle, git_buf *buf)
{
	size_t bytes_read = 0;
	do {
		char buffer[65536];
		command_read(handle, buffer, sizeof(buffer), &bytes_read);
		git_buf_put(buf, buffer, bytes_read);
	} while (bytes_read);

	return 0;
}
Beispiel #21
0
static int expandPerCentF(git_buf *buf, const char *replaceWith)
{
	ssize_t foundPercentage = git_buf_find(buf, '%');
	if (foundPercentage) {
		git_buf expanded = GIT_BUF_INIT;
		const char *end = buf->ptr + buf->size;
		const char *lastPercentage = buf->ptr;
		const char *idx = buf->ptr + foundPercentage;
		while (idx < end) {
			if (*idx == '%') {
				if (idx + 1 == end || (idx + 1 < end && *(idx + 1) == '%')) { // one '%' is at the end of the string OR "%%" is in the string
					git_buf_putc(&expanded, '%');
					++idx;
					++idx;
					lastPercentage = idx;
					continue;
				}
				// now we know, that we're not at the end of the string and that the next char is not '%'
				git_buf_put(&expanded, lastPercentage, idx - lastPercentage);
				++idx;
				if (*idx == 'f')
					git_buf_printf(&expanded, "\"%s\"", replaceWith);

				++idx;
				lastPercentage = idx;
				continue;
			}
			++idx;
		}
		if (lastPercentage)
			git_buf_put(&expanded, lastPercentage, idx - lastPercentage);
		if (git_buf_oom(&expanded))
		{
			giterr_set_oom();
			return -1;
		}
		git_buf_swap(buf, &expanded);
		git_buf_free(&expanded);
	}
	return 0;
}
Beispiel #22
0
static int append_abbreviated_oid(git_buf *out, const git_oid *b_commit)
{
	char *formatted_oid;

	formatted_oid = git_oid_allocfmt(b_commit);
	GITERR_CHECK_ALLOC(formatted_oid);

	git_buf_put(out, formatted_oid, 7);
	git__free(formatted_oid);

	return git_buf_oom(out) ? -1 : 0;
}
Beispiel #23
0
static int ident_remove_id(
	git_buf *to, const git_buf *from)
{
	const char *id_start, *id_end, *from_end = from->ptr + from->size;
	size_t need_size;

	if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
		return GIT_PASSTHROUGH;

	need_size = (size_t)(id_start - from->ptr) +
		4 /* "$Id$" */ + (size_t)(from_end - id_end);

	if (git_buf_grow(to, need_size) < 0)
		return -1;

	git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
	git_buf_put(to, "$Id$", 4);
	git_buf_put(to, id_end, (size_t)(from_end - id_end));

	return git_buf_oom(to) ? -1 : 0;
}
Beispiel #24
0
static void write_tree(git_buf *out, git_tree_cache *tree)
{
	size_t i;

	git_buf_printf(out, "%s%c%"PRIdZ" %"PRIuZ"\n", tree->name, 0, tree->entry_count, tree->children_count);

	if (tree->entry_count != -1)
		git_buf_put(out, (const char *) &tree->oid, GIT_OID_RAWSZ);

	for (i = 0; i < tree->children_count; i++)
		write_tree(out, tree->children[i]);
}
Beispiel #25
0
static int diff_print_to_buffer_cb(
	const git_diff_delta *delta,
	const git_diff_range *range,
	char line_origin,
	const char *content,
	size_t content_len,
	void *payload)
{
	git_buf *output = payload;
	GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(line_origin);
	return git_buf_put(output, content, content_len);
}
Beispiel #26
0
static int on_header_value(http_parser *parser, const char *str, size_t len)
{
	transport_http *t = (transport_http *) parser->data;
	git_buf *buf = &t->buf;

	if (t->ct_finished) {
		t->last_cb = VALUE;
		return 0;
	}

	if (t->last_cb == VALUE)
		git_buf_put(buf, str, len);

	if (t->last_cb == FIELD && !strcmp(git_buf_cstr(buf), typestr)) {
		t->ct_found = 1;
		git_buf_clear(buf);
		git_buf_put(buf, str, len);
	}

	t->last_cb = VALUE;

	return git_buf_oom(buf);
}
Beispiel #27
0
static int on_header_value(http_parser *parser, const char *str, size_t len)
{
	parser_context *ctx = (parser_context *) parser->data;
	http_subtransport *t = ctx->t;

	assert(NONE != t->last_cb);

	if (FIELD == t->last_cb)
		git_buf_clear(&t->parse_header_value);

	if (git_buf_put(&t->parse_header_value, str, len) < 0)
		return t->parse_error = PARSE_ERROR_GENERIC;

	t->last_cb = VALUE;
	return 0;
}
Beispiel #28
0
int git_path_diriter_next(git_path_diriter *diriter)
{
	struct dirent *de;
	const char *filename;
	size_t filename_len;
	bool skip_dot = !(diriter->flags & GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
	int error = 0;

	assert(diriter);

	errno = 0;

	do {
		if ((de = readdir(diriter->dir)) == NULL) {
			if (!errno)
				return GIT_ITEROVER;

			giterr_set(GITERR_OS,
				"Could not read directory '%s'", diriter->path);
			return -1;
		}
	} while (skip_dot && git_path_is_dot_or_dotdot(de->d_name));

	filename = de->d_name;
	filename_len = strlen(filename);

#ifdef GIT_USE_ICONV
	if ((diriter->flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0 &&
		(error = git_path_iconv(&diriter->ic, &filename, &filename_len)) < 0)
		return error;
#endif

	git_buf_truncate(&diriter->path, diriter->parent_len);

	if (diriter->parent_len > 0 &&
		diriter->path.ptr[diriter->parent_len-1] != '/')
		git_buf_putc(&diriter->path, '/');

	git_buf_put(&diriter->path, filename, filename_len);

	if (git_buf_oom(&diriter->path))
		return -1;

	return error;
}
Beispiel #29
0
int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
{
    const char *start = src->ptr;
    const char *end = start + src->size;
    const char *scan = start;
    const char *next = memchr(scan, '\n', src->size);
    size_t alloclen;

    assert(tgt != src);

    if (!next)
        return git_buf_set(tgt, src->ptr, src->size);

    /* attempt to reduce reallocs while in the loop */
    GITERR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
    GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
    if (git_buf_grow(tgt, alloclen) < 0)
        return -1;
    tgt->size = 0;

    for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
        size_t copylen = next - scan;

        /* if we find mixed line endings, bail */
        if (next > start && next[-1] == '\r') {
            git_buf_free(tgt);
            return GIT_PASSTHROUGH;
        }

        GITERR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
        if (git_buf_grow_by(tgt, alloclen) < 0)
            return -1;

        if (next > scan) {
            memcpy(tgt->ptr + tgt->size, scan, copylen);
            tgt->size += copylen;
        }

        tgt->ptr[tgt->size++] = '\r';
        tgt->ptr[tgt->size++] = '\n';
    }

    tgt->ptr[tgt->size] = '\0';
    return git_buf_put(tgt, scan, end - scan);
}
Beispiel #30
0
/**
 * Append to 'out' properly marking continuations when there's a newline in 'content'
 */
static void format_header_field(git_buf *out, const char *field, const char *content)
{
	const char *lf;

	assert(out && field && content);

	git_buf_puts(out, field);
	git_buf_putc(out, ' ');

	while ((lf = strchr(content, '\n')) != NULL) {
		git_buf_put(out, content, lf - content);
		git_buf_puts(out, "\n ");
		content = lf + 1;
	}

	git_buf_puts(out, content);
	git_buf_putc(out, '\n');
}