Ejemplo n.º 1
0
static int write_index(git_index *index, git_filebuf *file)
{
	int error = GIT_SUCCESS;
	git_oid hash_final;

	struct index_header header;

	int is_extended;

	assert(index && file);

	is_extended = is_index_extended(index);

	header.signature = htonl(INDEX_HEADER_SIG);
	header.version = htonl(is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER);
	header.entry_count = htonl(index->entries.length);

	git_filebuf_write(file, &header, sizeof(struct index_header));

	error = write_entries(index, file);
	if (error < GIT_SUCCESS)
		return git__rethrow(error, "Failed to write index");

	/* TODO: write extensions (tree cache) */

	/* get out the hash for all the contents we've appended to the file */
	git_filebuf_hash(&hash_final, file);

	/* write it at the end of the file */
	git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ);

	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write index");
}
Ejemplo n.º 2
0
int git_blob_create_fromchunks(
	git_oid *oid,
	git_repository *repo,
	const char *hintpath,
	int (*source_cb)(char *content, size_t max_length, void *payload),
	void *payload)
{
	int error;
	char *content = NULL;
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf path = GIT_BUF_INIT;

	assert(oid && repo && source_cb);

	if ((error = git_buf_joinpath(
			&path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
		goto cleanup;

	content = git__malloc(BUFFER_SIZE);
	GITERR_CHECK_ALLOC(content);

	if ((error = git_filebuf_open(
			&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY, 0666)) < 0)
		goto cleanup;

	while (1) {
		int read_bytes = source_cb(content, BUFFER_SIZE, payload);

		if (!read_bytes)
			break;

		if (read_bytes > BUFFER_SIZE) {
			giterr_set(GITERR_OBJECT, "Invalid chunk size while creating blob");
			error = GIT_EBUFS;
		} else if (read_bytes < 0) {
			error = giterr_set_after_callback(read_bytes);
		} else {
			error = git_filebuf_write(&file, content, read_bytes);
		}

		if (error < 0)
			goto cleanup;
	}

	if ((error = git_filebuf_flush(&file)) < 0)
		goto cleanup;

	error = git_blob__create_from_paths(
		oid, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL);

cleanup:
	git_buf_free(&path);
	git_filebuf_cleanup(&file);
	git__free(content);

	return error;
}
Ejemplo n.º 3
0
int git_filebuf_printf(git_filebuf *file, const char *format, ...)
{
	va_list arglist;
	size_t space_left;
	int len, res;
	char *tmp_buffer;

	ENSURE_BUF_OK(file);

	space_left = file->buf_size - file->buf_pos;

	do {
		va_start(arglist, format);
		len = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
		va_end(arglist);

		if (len < 0) {
			file->last_error = BUFERR_MEM;
			return -1;
		}

		if ((size_t)len + 1 <= space_left) {
			file->buf_pos += len;
			return 0;
		}

		if (flush_buffer(file) < 0)
			return -1;

		space_left = file->buf_size - file->buf_pos;

	} while ((size_t)len + 1 <= space_left);

	tmp_buffer = git__malloc(len + 1);
	if (!tmp_buffer) {
		file->last_error = BUFERR_MEM;
		return -1;
	}

	va_start(arglist, format);
	len = p_vsnprintf(tmp_buffer, len + 1, format, arglist);
	va_end(arglist);

	if (len < 0) {
		git__free(tmp_buffer);
		file->last_error = BUFERR_MEM;
		return -1;
	}

	res = git_filebuf_write(file, tmp_buffer, len);
	git__free(tmp_buffer);

	return res;
}
Ejemplo n.º 4
0
Archivo: blob.c Proyecto: 0CV0/libgit2
int git_blob_create_fromchunks(
	git_oid *oid,
	git_repository *repo,
	const char *hintpath,
	int (*source_cb)(char *content, size_t max_length, void *payload),
	void *payload)
{
	int error = -1, read_bytes;
	char *content = NULL;
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf path = GIT_BUF_INIT;

	if (git_buf_join_n(
		&path, '/', 3, 
		git_repository_path(repo),
		GIT_OBJECTS_DIR, 
		"streamed") < 0)
			goto cleanup;

	content = git__malloc(BUFFER_SIZE);
	GITERR_CHECK_ALLOC(content);

	if (git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY) < 0)
		goto cleanup;

	while (1) {
		read_bytes = source_cb(content, BUFFER_SIZE, payload);

		assert(read_bytes <= BUFFER_SIZE);

		if (read_bytes <= 0)
			break;

		if (git_filebuf_write(&file, content, read_bytes) < 0)
			goto cleanup;
	}

	if (read_bytes < 0)
		goto cleanup;

	if (git_filebuf_flush(&file) < 0)
		goto cleanup;

	error = blob_create_internal(oid, repo, file.path_lock, hintpath, hintpath != NULL);

cleanup:
	git_buf_free(&path);
	git_filebuf_cleanup(&file);
	git__free(content);
	return error;
}
Ejemplo n.º 5
0
static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type)
{
	int error = 0;
	git_buf final_path = GIT_BUF_INIT;
	char header[MAX_HEADER_LEN];
	size_t header_len;
	git_filebuf fbuf = GIT_FILEBUF_INIT;
	loose_backend *backend;

	backend = (loose_backend *)_backend;

	/* prepare the header for the file */
	if ((error = git_odb__format_object_header(&header_len,
		header, sizeof(header), len, type)) < 0)
		goto cleanup;

	if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
		git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
			backend->object_file_mode) < 0)
	{
		error = -1;
		goto cleanup;
	}

	git_filebuf_write(&fbuf, header, header_len);
	git_filebuf_write(&fbuf, data, len);

	if (object_file_name(&final_path, backend, oid) < 0 ||
		object_mkdir(&final_path, backend) < 0 ||
		git_filebuf_commit_at(&fbuf, final_path.ptr) < 0)
		error = -1;

cleanup:
	if (error < 0)
		git_filebuf_cleanup(&fbuf);
	git_buf_dispose(&final_path);
	return error;
}
Ejemplo n.º 6
0
/* make sure git_filebuf_write writes large buffer correctly */
void test_core_filebuf__2(void)
{
	git_filebuf file;
	char test[] = "test";
	unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */

	memset(buf, 0xfe, sizeof(buf));

	cl_git_pass(git_filebuf_open(&file, test, 0));
	cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf)));
	cl_git_pass(git_filebuf_commit(&file));

	cl_must_pass(p_unlink(test));
}
Ejemplo n.º 7
0
/* make sure git_filebuf_write writes large buffer correctly */
void test_core_filebuf__2(void)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	char test[] = "test";
	unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */

	memset(buf, 0xfe, sizeof(buf));

	cl_git_pass(git_filebuf_open(&file, test, 0, 0666));
	cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf)));
	cl_git_pass(git_filebuf_commit(&file));

	cl_assert_equal_file((char *)buf, sizeof(buf), test);

	cl_must_pass(p_unlink(test));
}
Ejemplo n.º 8
0
Archivo: tests.c Proyecto: 1336/libgit2
void test_index_tests__add(void)
{
	git_index *index;
	git_filebuf file = GIT_FILEBUF_INIT;
	git_repository *repo;
	const git_index_entry *entry;
	git_oid id1;

	cl_set_cleanup(&cleanup_myrepo, NULL);

	/* Intialize a new repository */
	cl_git_pass(git_repository_init(&repo, "./myrepo", 0));

	/* Ensure we're the only guy in the room */
	cl_git_pass(git_repository_index(&index, repo));
	cl_assert(git_index_entrycount(index) == 0);

	/* Create a new file in the working directory */
	cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
	cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666));
	cl_git_pass(git_filebuf_write(&file, "hey there\n", 10));
	cl_git_pass(git_filebuf_commit(&file));

	/* Store the expected hash of the file/blob
	 * This has been generated by executing the following
	 * $ echo "hey there" | git hash-object --stdin
	 */
	cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));

	/* Add the new file to the index */
	cl_git_pass(git_index_add_bypath(index, "test.txt"));

	/* Wow... it worked! */
	cl_assert(git_index_entrycount(index) == 1);
	entry = git_index_get_byindex(index, 0);

	/* And the built-in hashing mechanism worked as expected */
	cl_assert_equal_oid(&id1, &entry->id);

	/* Test access by path instead of index */
	cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
	cl_assert_equal_oid(&id1, &entry->id);

	git_index_free(index);
	git_repository_free(repo);
}
Ejemplo n.º 9
0
static int blob_writestream_write(git_writestream *_stream, const char *buffer, size_t len)
{
	blob_writestream *stream = (blob_writestream *) _stream;

	return git_filebuf_write(&stream->fbuf, buffer, len);
}
Ejemplo n.º 10
0
Archivo: tests.c Proyecto: 1336/libgit2
void test_index_tests__add_frombuffer_reset_entry(void)
{
	git_index *index;
	git_repository *repo;
        git_index_entry entry;
	const git_index_entry *returned_entry;
	git_filebuf file = GIT_FILEBUF_INIT;

	git_oid id1;
	git_blob *blob;
	const char *old_content = "here\n";
	const char *content = "hey there\n";

	cl_set_cleanup(&cleanup_myrepo, NULL);

	/* Intialize a new repository */
	cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
	cl_git_pass(git_repository_index(&index, repo));
	cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
	cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666));
	cl_git_pass(git_filebuf_write(&file, old_content, strlen(old_content)));
	cl_git_pass(git_filebuf_commit(&file));

	/* Store the expected hash of the file/blob
	 * This has been generated by executing the following
	 * $ echo "hey there" | git hash-object --stdin
	 */
	cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));

	cl_git_pass(git_index_add_bypath(index, "test.txt"));

	/* Add the new file to the index */
	memset(&entry, 0x0, sizeof(git_index_entry));
	entry.mode = GIT_FILEMODE_BLOB;
	entry.path = "test.txt";
	cl_git_pass(git_index_add_frombuffer(index, &entry,
		content, strlen(content)));

	/* Wow... it worked! */
	cl_assert(git_index_entrycount(index) == 1);
	returned_entry = git_index_get_byindex(index, 0);

	/* And the built-in hashing mechanism worked as expected */
	cl_assert_equal_oid(&id1, &returned_entry->id);
	/* And mode is the one asked */
	cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode);

	/* Test access by path instead of index */
	cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
	cl_assert_equal_oid(&id1, &returned_entry->id);
	cl_assert_equal_i(0, returned_entry->dev);
	cl_assert_equal_i(0, returned_entry->ino);
	cl_assert_equal_i(0, returned_entry->uid);
	cl_assert_equal_i(0, returned_entry->uid);
	cl_assert_equal_i(10, returned_entry->file_size);

            /* Test the blob is in the repository */
	cl_git_pass(git_blob_lookup(&blob, repo, &id1));
	cl_assert_equal_s(content, git_blob_rawcontent(blob));
	git_blob_free(blob);

	git_index_free(index);
	git_repository_free(repo);
}
Ejemplo n.º 11
0
static int loose_backend__writestream_write(git_odb_stream *_stream, const char *data, size_t len)
{
	loose_writestream *stream = (loose_writestream *)_stream;
	return git_filebuf_write(&stream->fbuf, data, len);
}
Ejemplo n.º 12
0
/* Receiving data from a socket and storing it is pretty much the same for git and HTTP */
int git_fetch__download_pack(
	char **out,
	const char *buffered,
	size_t buffered_size,
	GIT_SOCKET fd,
	git_repository *repo)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	int error;
	char buff[1024];
	git_buf path = GIT_BUF_INIT;
	static const char suff[] = "/objects/pack/pack-received";
	gitno_buffer buf;

	gitno_buffer_setup(&buf, buff, sizeof(buff), fd);

	if (memcmp(buffered, "PACK", strlen("PACK"))) {
		return git__throw(GIT_ERROR, "The pack doesn't start with the signature");
	}

	error = git_buf_joinpath(&path, repo->path_repository, suff);
	if (error < GIT_SUCCESS)
		goto cleanup;

	error = git_filebuf_open(&file, path.ptr, GIT_FILEBUF_TEMPORARY);
	if (error < GIT_SUCCESS)
		goto cleanup;

	/* Part of the packfile has been received, don't loose it */
	error = git_filebuf_write(&file, buffered, buffered_size);
	if (error < GIT_SUCCESS)
		goto cleanup;

	while (1) {
		error = git_filebuf_write(&file, buf.data, buf.offset);
		if (error < GIT_SUCCESS)
			goto cleanup;

		gitno_consume_n(&buf, buf.offset);
		error = gitno_recv(&buf);
		if (error < GIT_SUCCESS)
			goto cleanup;
		if (error == 0) /* Orderly shutdown */
			break;
	}

	*out = git__strdup(file.path_lock);
	if (*out == NULL) {
		error = GIT_ENOMEM;
		goto cleanup;
	}

	/* A bit dodgy, but we need to keep the pack at the temporary path */
	error = git_filebuf_commit_at(&file, file.path_lock, GIT_PACK_FILE_MODE);
cleanup:
	if (error < GIT_SUCCESS)
		git_filebuf_cleanup(&file);
    git_buf_free(&path);

	return error;
}
Ejemplo n.º 13
0
int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
{
	git_mwindow *w = NULL;
	unsigned int i, long_offsets = 0, left;
	int error;
	struct git_pack_idx_header hdr;
	git_buf filename = GIT_BUF_INIT;
	struct entry *entry;
	git_oid trailer_hash, file_hash;
	git_hash_ctx ctx;
	git_filebuf index_file = {0};
	void *packfile_trailer;

	if (git_hash_ctx_init(&ctx) < 0)
		return -1;

	/* Test for this before resolve_deltas(), as it plays with idx->off */
	if (idx->off < idx->pack->mwf.size - 20) {
		giterr_set(GITERR_INDEXER, "Unexpected data at the end of the pack");
		return -1;
	}

	packfile_trailer = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left);
	if (packfile_trailer == NULL) {
		git_mwindow_close(&w);
		goto on_error;
	}

	/* Compare the packfile trailer as it was sent to us and what we calculated */
	git_oid_fromraw(&file_hash, (unsigned char*) packfile_trailer);
	git_mwindow_close(&w);

	git_hash_final(&trailer_hash, &idx->trailer);
	if (git_oid_cmp(&file_hash, &trailer_hash)) {
		giterr_set(GITERR_INDEXER, "packfile trailer mismatch");
		return -1;
	}

	/* Freeze the number of deltas */
	stats->total_deltas = stats->total_objects - stats->indexed_objects;

	if ((error = resolve_deltas(idx, stats)) < 0)
		return error;

	if (stats->indexed_objects != stats->total_objects) {
		giterr_set(GITERR_INDEXER, "early EOF");
		return -1;
	}

	if (stats->local_objects > 0) {
		if (update_header_and_rehash(idx, stats) < 0)
			return -1;

		git_hash_final(&trailer_hash, &idx->trailer);
		write_at(idx, &trailer_hash, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ);
	}

	git_vector_sort(&idx->objects);

	git_buf_sets(&filename, idx->pack->pack_name);
	git_buf_shorten(&filename, strlen("pack"));
	git_buf_puts(&filename, "idx");
	if (git_buf_oom(&filename))
		return -1;

	if (git_filebuf_open(&index_file, filename.ptr,
		GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0)
		goto on_error;

	/* Write out the header */
	hdr.idx_signature = htonl(PACK_IDX_SIGNATURE);
	hdr.idx_version = htonl(2);
	git_filebuf_write(&index_file, &hdr, sizeof(hdr));

	/* Write out the fanout table */
	for (i = 0; i < 256; ++i) {
		uint32_t n = htonl(idx->fanout[i]);
		git_filebuf_write(&index_file, &n, sizeof(n));
	}

	/* Write out the object names (SHA-1 hashes) */
	git_vector_foreach(&idx->objects, i, entry, struct entry*) {
		git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid));
		git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ);
	}
	git_hash_final(&idx->hash, &ctx);

	/* Write out the CRC32 values */
	git_vector_foreach(&idx->objects, i, entry, struct entry*) {
		git_filebuf_write(&index_file, &entry->crc, sizeof(uint32_t));
	}

	/* Write out the offsets */
	git_vector_foreach(&idx->objects, i, entry, struct entry*) {
		uint32_t n;

		if (entry->offset == UINT32_MAX)
			n = htonl(0x80000000 | long_offsets++);
		else
			n = htonl(entry->offset);

		git_filebuf_write(&index_file, &n, sizeof(uint32_t));
	}

	/* Write out the long offsets */
	git_vector_foreach(&idx->objects, i, entry, struct entry*) {
		uint32_t split[2];

		if (entry->offset != UINT32_MAX)
			continue;

		split[0] = htonl(entry->offset_long >> 32);
		split[1] = htonl(entry->offset_long & 0xffffffff);

		git_filebuf_write(&index_file, &split, sizeof(uint32_t) * 2);
	}

	/* Write out the packfile trailer to the index */
	if (git_filebuf_write(&index_file, &trailer_hash, GIT_OID_RAWSZ) < 0)
		goto on_error;

	/* Write out the hash of the idx */
	if (git_filebuf_hash(&trailer_hash, &index_file) < 0)
		goto on_error;

	git_filebuf_write(&index_file, &trailer_hash, sizeof(git_oid));

	/* Figure out what the final name should be */
	if (index_path(&filename, idx, ".idx") < 0)
		goto on_error;

	/* Commit file */
	if (git_filebuf_commit_at(&index_file, filename.ptr) < 0)
		goto on_error;

	git_mwindow_free_all(&idx->pack->mwf);
	/* We need to close the descriptor here so Windows doesn't choke on commit_at */
	if (p_close(idx->pack->mwf.fd) < 0) {
		giterr_set(GITERR_OS, "failed to close packfile");
		goto on_error;
	}

	idx->pack->mwf.fd = -1;

	if (index_path(&filename, idx, ".pack") < 0)
		goto on_error;

	/* And don't forget to rename the packfile to its new place. */
	p_rename(idx->pack->pack_name, git_buf_cstr(&filename));

	git_buf_free(&filename);
	git_hash_ctx_cleanup(&ctx);
	return 0;

on_error:
	git_mwindow_free_all(&idx->pack->mwf);
	git_filebuf_cleanup(&index_file);
	git_buf_free(&filename);
	git_hash_ctx_cleanup(&ctx);
	return -1;
}
Ejemplo n.º 14
0
BEGIN_TEST(config16, "add a variable in a new section")
	git_config *cfg;
	int i;
	git_filebuf buf;

	/* By freeing the config, we make sure we flush the values  */
	must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
	must_pass(git_config_set_int(cfg, "section.tmp", 5));
	must_pass(git_config_get_int(cfg, "section.tmp", &i));
	must_be_true(i == 5);
	must_pass(git_config_delete(cfg, "section.tmp"));
	git_config_free(cfg);

	/* As the section wasn't removed, owerwrite the file */
	must_pass(git_filebuf_open(&buf, CONFIG_BASE "/config10", 0));
	must_pass(git_filebuf_write(&buf, "[empty]\n", strlen("[empty]\n")));
	must_pass(git_filebuf_commit(&buf));
END_TEST

BEGIN_SUITE(config)
	 ADD_TEST(config0);
	 ADD_TEST(config1);
	 ADD_TEST(config2);
	 ADD_TEST(config3);
	 ADD_TEST(config4);
	 ADD_TEST(config5);
	 ADD_TEST(config6);
	 ADD_TEST(config7);
	 ADD_TEST(config8);
	 ADD_TEST(config9);
	 ADD_TEST(config10);