Ejemplo n.º 1
0
void test_core_filebuf__symlink_follow(void)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	const char *dir = "linkdir", *source = "linkdir/link";

#ifdef GIT_WIN32
	cl_skip();
#endif

	cl_git_pass(p_mkdir(dir, 0777));
	cl_git_pass(p_symlink("target", source));

	cl_git_pass(git_filebuf_open(&file, source, 0, 0666));
	cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));

	cl_assert_equal_i(true, git_path_exists("linkdir/target.lock"));

	cl_git_pass(git_filebuf_commit(&file));
	cl_assert_equal_i(true, git_path_exists("linkdir/target"));

	git_filebuf_cleanup(&file);

	/* The second time around, the target file does exist */
	cl_git_pass(git_filebuf_open(&file, source, 0, 0666));
	cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));

	cl_assert_equal_i(true, git_path_exists("linkdir/target.lock"));

	cl_git_pass(git_filebuf_commit(&file));
	cl_assert_equal_i(true, git_path_exists("linkdir/target"));

	git_filebuf_cleanup(&file);
	cl_git_pass(git_futils_rmdir_r(dir, NULL, GIT_RMDIR_REMOVE_FILES));
}
Ejemplo n.º 2
0
static int repo_init_create_head(const char *git_dir, const char *ref_name)
{
	git_buf ref_path = GIT_BUF_INIT;
	git_filebuf ref = GIT_FILEBUF_INIT;
	const char *fmt;

	if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
		git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE) < 0)
		goto fail;

	if (!ref_name)
		ref_name = GIT_BRANCH_MASTER;

	if (git__prefixcmp(ref_name, GIT_REFS_DIR) == 0)
		fmt = "ref: %s\n";
	else
		fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n";

	if (git_filebuf_printf(&ref, fmt, ref_name) < 0 ||
		git_filebuf_commit(&ref) < 0)
		goto fail;

	git_buf_free(&ref_path);
	return 0;

fail:
	git_buf_free(&ref_path);
	git_filebuf_cleanup(&ref);
	return -1;
}
Ejemplo n.º 3
0
void test_core_filebuf__rename_error(void)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	char *dir = "subdir",  *test = "subdir/test", *test_lock = "subdir/test.lock";
	int fd;

#ifndef GIT_WIN32
	cl_skip();
#endif

	cl_git_pass(p_mkdir(dir, 0666));
	cl_git_mkfile(test, "dummy content");
	fd = p_open(test, O_RDONLY);
	cl_assert(fd > 0);
	cl_git_pass(git_filebuf_open(&file, test, 0, 0666));

	cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));

	cl_assert_equal_i(true, git_path_exists(test_lock));

	cl_git_fail(git_filebuf_commit(&file));
	p_close(fd);

	git_filebuf_cleanup(&file);

	cl_assert_equal_i(false, git_path_exists(test_lock));
}
Ejemplo n.º 4
0
static int write_merge_msg(
	git_repository *repo,
	const char *commit_oidstr,
	const char *commit_msgline)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf file_path = GIT_BUF_INIT;
	int error = 0;

	if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
		(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_REVERT_FILE_MODE)) < 0 ||
		(error = git_filebuf_printf(&file, "Revert \"%s\"\n\nThis reverts commit %s.\n",
		commit_msgline, commit_oidstr)) < 0)
		goto cleanup;

	error = git_filebuf_commit(&file);

cleanup:
	if (error < 0)
		git_filebuf_cleanup(&file);

	git_buf_free(&file_path);

	return error;
}
Ejemplo n.º 5
0
int git_index_write(git_index *index)
{
	git_filebuf file;
	struct stat indexst;
	int error;

	git_vector_sort(&index->entries);

	if ((error = git_filebuf_open(&file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < GIT_SUCCESS)
		return git__rethrow(error, "Failed to write index");

	if ((error = write_index(index, &file)) < GIT_SUCCESS) {
		git_filebuf_cleanup(&file);
		return git__rethrow(error, "Failed to write index");
	}

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

	if (p_stat(index->index_file_path, &indexst) == 0) {
		index->last_modified = indexst.st_mtime;
		index->on_disk = 1;
	}

	return GIT_SUCCESS;
}
Ejemplo n.º 6
0
Archivo: tests.c Proyecto: 1336/libgit2
void test_index_tests__elocked(void)
{
	git_repository *repo;
	git_index *index;
	git_filebuf file = GIT_FILEBUF_INIT;
	const git_error *err;
	int error;

	cl_set_cleanup(&cleanup_myrepo, NULL);

	cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
	cl_git_pass(git_repository_index(&index, repo));

	/* Lock the index file so we fail to lock it */
	cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666));
	error = git_index_write(index);
	cl_assert_equal_i(GIT_ELOCKED, error);

	err = giterr_last();
	cl_assert_equal_i(err->klass, GITERR_INDEX);

	git_filebuf_cleanup(&file);
	git_index_free(index);
	git_repository_free(repo);
}
Ejemplo n.º 7
0
static void loose_backend__writestream_free(git_odb_stream *_stream)
{
	loose_writestream *stream = (loose_writestream *)_stream;

	git_filebuf_cleanup(&stream->fbuf);
	git__free(stream);
}
Ejemplo n.º 8
0
static int blob_writestream_close(git_writestream *_stream)
{
	blob_writestream *stream = (blob_writestream *) _stream;

	git_filebuf_cleanup(&stream->fbuf);
	return 0;
}
Ejemplo n.º 9
0
void test_core_filebuf__hidden_file(void)
{
#ifndef GIT_WIN32
	cl_skip();
#else
	git_filebuf file = GIT_FILEBUF_INIT;
	char *dir = "hidden", *test = "hidden/test";
	bool hidden;

	cl_git_pass(p_mkdir(dir, 0666));
	cl_git_mkfile(test, "dummy content");

	cl_git_pass(git_win32__set_hidden(test, true));
	cl_git_pass(git_win32__hidden(&hidden, test));
	cl_assert(hidden);

	cl_git_pass(git_filebuf_open(&file, test, 0, 0666));

	cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));

	cl_git_pass(git_filebuf_commit(&file));

	git_filebuf_cleanup(&file);
#endif
}
Ejemplo n.º 10
0
static void blob_writestream_free(git_writestream *_stream)
{
	blob_writestream *stream = (blob_writestream *) _stream;

	git_filebuf_cleanup(&stream->fbuf);
	git__free(stream->hintpath);
	git__free(stream);
}
Ejemplo n.º 11
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.º 12
0
int git_filebuf_commit(git_filebuf *file, mode_t mode)
{
	/* temporary files cannot be committed */
	assert(file && file->path_original);

	file->flush_mode = Z_FINISH;
	flush_buffer(file);

	if (verify_last_error(file) < 0)
		goto on_error;

	file->fd_is_open = false;

	if (p_close(file->fd) < 0) {
		giterr_set(GITERR_OS, "Failed to close file at '%s'", file->path_lock);
		goto on_error;
	}

	file->fd = -1;

	if (p_chmod(file->path_lock, mode)) {
		giterr_set(GITERR_OS, "Failed to set attributes for file at '%s'", file->path_lock);
		goto on_error;
	}

	p_unlink(file->path_original);

	if (p_rename(file->path_lock, file->path_original) < 0) {
		giterr_set(GITERR_OS, "Failed to rename lockfile to '%s'", file->path_original);
		goto on_error;
	}

	git_filebuf_cleanup(file);
	return 0;

on_error:
	git_filebuf_cleanup(file);
	return -1;
}
Ejemplo n.º 13
0
/* make sure git_filebuf_cleanup clears the buffer */
void test_core_filebuf__4(void)
{
	git_filebuf file = GIT_FILEBUF_INIT;
	char test[] = "test";

	cl_assert(file.buffer == NULL);

	cl_git_pass(git_filebuf_open(&file, test, 0, 0666));
	cl_assert(file.buffer != NULL);

	git_filebuf_cleanup(&file);
	cl_assert(file.buffer == NULL);
}
Ejemplo n.º 14
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.º 15
0
int git_filebuf_commit(git_filebuf *file)
{
	int error;

	if ((error = flush_buffer(file)) < GIT_SUCCESS)
		goto cleanup;

	gitfo_close(file->fd);
	file->fd = -1;

	error = gitfo_move_file(file->path_lock, file->path_original);

cleanup:
	git_filebuf_cleanup(file);
	return error;
}
Ejemplo n.º 16
0
static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type)
{
	loose_backend *backend;
	loose_writestream *stream = NULL;
	char hdr[MAX_HEADER_LEN];
	git_buf tmp_path = GIT_BUF_INIT;
	size_t hdrlen;
	int error;

	assert(_backend && length >= 0);

	backend = (loose_backend *)_backend;
	*stream_out = NULL;

	if ((error = git_odb__format_object_header(&hdrlen,
		hdr, sizeof(hdr), length, type)) < 0)
		return error;

	stream = git__calloc(1, sizeof(loose_writestream));
	GITERR_CHECK_ALLOC(stream);

	stream->stream.backend = _backend;
	stream->stream.read = NULL; /* read only */
	stream->stream.write = &loose_backend__writestream_write;
	stream->stream.finalize_write = &loose_backend__writestream_finalize;
	stream->stream.free = &loose_backend__writestream_free;
	stream->stream.mode = GIT_STREAM_WRONLY;

	if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
		git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
			backend->object_file_mode) < 0 ||
		stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
	{
		git_filebuf_cleanup(&stream->fbuf);
		git__free(stream);
		stream = NULL;
	}
	git_buf_dispose(&tmp_path);
	*stream_out = (git_odb_stream *)stream;

	return !stream ? -1 : 0;
}
Ejemplo n.º 17
0
static int write_cherry_pick_head(
    git_repository *repo,
    const char *commit_oidstr)
{
    git_filebuf file = GIT_FILEBUF_INIT;
    git_buf file_path = GIT_BUF_INIT;
    int error = 0;

    if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_CHERRY_PICK_HEAD_FILE)) >= 0 &&
            (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRY_PICK_FILE_MODE)) >= 0 &&
            (error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
        error = git_filebuf_commit(&file);

    if (error < 0)
        git_filebuf_cleanup(&file);

    git_buf_free(&file_path);

    return error;
}
Ejemplo n.º 18
0
int git_filebuf_commit(git_filebuf *file)
{
    int error;

    /* temporary files cannot be committed */
    assert(file && file->path_original);

    file->flush_mode = Z_FINISH;
    if ((error = flush_buffer(file)) < GIT_SUCCESS)
        goto cleanup;

    gitfo_close(file->fd);
    file->fd = -1;

    error = gitfo_mv(file->path_lock, file->path_original);

cleanup:
    git_filebuf_cleanup(file);
    if (error < GIT_SUCCESS)
        return git__rethrow(error, "Failed to commit locked file from buffer");
    return GIT_SUCCESS;
}
Ejemplo n.º 19
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.º 20
0
static int write_merge_msg(
    git_repository *repo,
    const char *commit_msg)
{
    git_filebuf file = GIT_FILEBUF_INIT;
    git_buf file_path = GIT_BUF_INIT;
    int error = 0;

    if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
            (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRY_PICK_FILE_MODE)) < 0 ||
            (error = git_filebuf_printf(&file, "%s", commit_msg)) < 0)
        goto cleanup;

    error = git_filebuf_commit(&file);

cleanup:
    if (error < 0)
        git_filebuf_cleanup(&file);

    git_buf_free(&file_path);

    return error;
}
Ejemplo n.º 21
0
int git_filebuf_open(git_filebuf *file, const char *path, int flags)
{
    int error;
    size_t path_len;

    assert(file && path);

    memset(file, 0x0, sizeof(git_filebuf));

    file->buf_size = WRITE_BUFFER_SIZE;
    file->buf_pos = 0;
    file->fd = -1;

    /* Allocate the main cache buffer */
    file->buffer = git__malloc(file->buf_size);
    if (file->buffer == NULL) {
        error = GIT_ENOMEM;
        goto cleanup;
    }

    /* If we are hashing on-write, allocate a new hash context */
    if (flags & GIT_FILEBUF_HASH_CONTENTS) {
        if ((file->digest = git_hash_new_ctx()) == NULL) {
            error = GIT_ENOMEM;
            goto cleanup;
        }
    }

    /* If we are deflating on-write, */
    if (flags & GIT_FILEBUF_DEFLATE_CONTENTS) {

        /* Initialize the ZLib stream */
        if (deflateInit(&file->zs, Z_BEST_SPEED) != Z_OK) {
            error = git__throw(GIT_EZLIB, "Failed to initialize zlib");
            goto cleanup;
        }

        /* Allocate the Zlib cache buffer */
        file->z_buf = git__malloc(file->buf_size);
        if (file->z_buf == NULL) {
            error = GIT_ENOMEM;
            goto cleanup;
        }

        /* Never flush */
        file->flush_mode = Z_NO_FLUSH;
        file->write = &write_deflate;
    } else {
        file->write = &write_normal;
    }

    /* If we are writing to a temp file */
    if (flags & GIT_FILEBUF_TEMPORARY) {
        char tmp_path[GIT_PATH_MAX];

        /* Open the file as temporary for locking */
        file->fd = gitfo_mktemp(tmp_path, path);
        if (file->fd < 0) {
            error = GIT_EOSERR;
            goto cleanup;
        }

        /* No original path */
        file->path_original = NULL;
        file->path_lock = git__strdup(tmp_path);

        if (file->path_lock == NULL) {
            error = GIT_ENOMEM;
            goto cleanup;
        }
    } else {
        path_len = strlen(path);

        /* Save the original path of the file */
        file->path_original = git__strdup(path);
        if (file->path_original == NULL) {
            error = GIT_ENOMEM;
            goto cleanup;
        }

        /* create the locking path by appending ".lock" to the original */
        file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH);
        if (file->path_lock == NULL) {
            error = GIT_ENOMEM;
            goto cleanup;
        }

        memcpy(file->path_lock, file->path_original, path_len);
        memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH);

        /* open the file for locking */
        if ((error = lock_file(file, flags)) < GIT_SUCCESS)
            goto cleanup;
    }

    return GIT_SUCCESS;

cleanup:
    git_filebuf_cleanup(file);
    return git__rethrow(error, "Failed to open file buffer for '%s'", path);
}
Ejemplo n.º 22
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.º 23
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.º 24
0
int git_filebuf_open(git_filebuf *file, const char *path, int flags)
{
	int error;
	size_t path_len;

	if (file == NULL || path == NULL)
		return GIT_ERROR;

	memset(file, 0x0, sizeof(git_filebuf));

	file->buf_size = WRITE_BUFFER_SIZE;
	file->buf_pos = 0;
	file->fd = -1;

	path_len = strlen(path);

	file->path_original = git__strdup(path);
	if (file->path_original == NULL) {
		error = GIT_ENOMEM;
		goto cleanup;
	}

	file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH);
	if (file->path_lock == NULL) {
		error = GIT_ENOMEM;
		goto cleanup;
	}

	memcpy(file->path_lock, file->path_original, path_len);
	memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH);

	file->buffer = git__malloc(file->buf_size);
	if (file->buffer == NULL){
		error = GIT_ENOMEM;
		goto cleanup;
	}

#ifdef GIT_FILEBUF_THREADS
	file->buffer_back = git__malloc(file->buf_size);
	if (file->buffer_back == NULL){
		error = GIT_ENOMEM;
		goto cleanup;
	}
#endif

	if (flags & GIT_FILEBUF_HASH_CONTENTS) {
		if ((file->digest = git_hash_new_ctx()) == NULL) {
			error = GIT_ENOMEM;
			goto cleanup;
		}
	}

	if ((error = lock_file(file, flags)) < GIT_SUCCESS)
		goto cleanup;

	return GIT_SUCCESS;

cleanup:
	git_filebuf_cleanup(file);
	return error;
}
Ejemplo n.º 25
0
int git_filebuf_open(git_filebuf *file, const char *path, int flags)
{
	int compression;
	size_t path_len;

	/* opening an already open buffer is a programming error;
	 * assert that this never happens instead of returning
	 * an error code */
	assert(file && path && file->buffer == NULL);

	memset(file, 0x0, sizeof(git_filebuf));

	if (flags & GIT_FILEBUF_DO_NOT_BUFFER)
		file->do_not_buffer = true;

	file->buf_size = WRITE_BUFFER_SIZE;
	file->buf_pos = 0;
	file->fd = -1;
	file->last_error = BUFERR_OK;

	/* Allocate the main cache buffer */
	if (!file->do_not_buffer) {
		file->buffer = git__malloc(file->buf_size);
		GITERR_CHECK_ALLOC(file->buffer);
	}

	/* If we are hashing on-write, allocate a new hash context */
	if (flags & GIT_FILEBUF_HASH_CONTENTS) {
		file->digest = git_hash_new_ctx();
		GITERR_CHECK_ALLOC(file->digest);
	}

	compression = flags >> GIT_FILEBUF_DEFLATE_SHIFT;

	/* If we are deflating on-write, */
	if (compression != 0) {
		/* Initialize the ZLib stream */
		if (deflateInit(&file->zs, compression) != Z_OK) {
			giterr_set(GITERR_ZLIB, "Failed to initialize zlib");
			goto cleanup;
		}

		/* Allocate the Zlib cache buffer */
		file->z_buf = git__malloc(file->buf_size);
		GITERR_CHECK_ALLOC(file->z_buf);

		/* Never flush */
		file->flush_mode = Z_NO_FLUSH;
		file->write = &write_deflate;
	} else {
		file->write = &write_normal;
	}

	/* If we are writing to a temp file */
	if (flags & GIT_FILEBUF_TEMPORARY) {
		git_buf tmp_path = GIT_BUF_INIT;

		/* Open the file as temporary for locking */
		file->fd = git_futils_mktmp(&tmp_path, path);

		if (file->fd < 0) {
			git_buf_free(&tmp_path);
			goto cleanup;
		}
		file->fd_is_open = true;

		/* No original path */
		file->path_original = NULL;
		file->path_lock = git_buf_detach(&tmp_path);
		GITERR_CHECK_ALLOC(file->path_lock);
	} else {
		path_len = strlen(path);

		/* Save the original path of the file */
		file->path_original = git__strdup(path);
		GITERR_CHECK_ALLOC(file->path_original);

		/* create the locking path by appending ".lock" to the original */
		file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH);
		GITERR_CHECK_ALLOC(file->path_lock);

		memcpy(file->path_lock, file->path_original, path_len);
		memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH);

		/* open the file for locking */
		if (lock_file(file, flags) < 0)
			goto cleanup;
	}

	return 0;

cleanup:
	git_filebuf_cleanup(file);
	return -1;
}