Beispiel #1
0
int git_patch_parse(
	git_patch **out,
	git_patch_parse_ctx *ctx)
{
	git_patch_parsed *patch;
	size_t start, used;
	int error = 0;

	assert(out && ctx);

	*out = NULL;

	patch = git__calloc(1, sizeof(git_patch_parsed));
	GITERR_CHECK_ALLOC(patch);

	patch->ctx = ctx;
	GIT_REFCOUNT_INC(patch->ctx);

	patch->base.free_fn = patch_parsed__free;

	patch->base.delta = git__calloc(1, sizeof(git_diff_delta));
	GITERR_CHECK_ALLOC(patch->base.delta);

	patch->base.delta->status = GIT_DELTA_MODIFIED;
	patch->base.delta->nfiles = 2;

	start = ctx->parse_ctx.remain_len;

	if ((error = parse_patch_header(patch, ctx)) < 0 ||
		(error = parse_patch_body(patch, ctx)) < 0 ||
		(error = check_patch(patch)) < 0)
		goto done;

	used = start - ctx->parse_ctx.remain_len;
	ctx->parse_ctx.remain += used;

	patch->base.diff_opts.old_prefix = patch->old_prefix;
	patch->base.diff_opts.new_prefix = patch->new_prefix;
	patch->base.diff_opts.flags |= GIT_DIFF_SHOW_BINARY;

	GIT_REFCOUNT_INC(&patch->base);
	*out = &patch->base;

done:
	if (error < 0)
		patch_parsed__free(&patch->base);

	return error;
}
Beispiel #2
0
/* lookup submodule or return ENOTFOUND if it doesn't exist */
static int submodule_lookup(
	git_submodule **out,
	git_submodule_cache *cache,
	const char *name,
	const char *alternate)
{
	khiter_t pos;

	/* lock cache */

	pos = git_strmap_lookup_index(cache->submodules, name);

	if (!git_strmap_valid_index(cache->submodules, pos) && alternate)
		pos = git_strmap_lookup_index(cache->submodules, alternate);

	if (!git_strmap_valid_index(cache->submodules, pos)) {
		/* unlock cache */
		return GIT_ENOTFOUND; /* don't set error - caller will cope */
	}

	if (out != NULL) {
		git_submodule *sm = git_strmap_value_at(cache->submodules, pos);
		GIT_REFCOUNT_INC(sm);
		*out = sm;
	}

	/* unlock cache */

	return 0;
}
Beispiel #3
0
git_patch_parse_ctx *git_patch_parse_ctx_init(
	const char *content,
	size_t content_len,
	const git_patch_options *opts)
{
	git_patch_parse_ctx *ctx;
	git_patch_options default_opts = GIT_PATCH_OPTIONS_INIT;

	if ((ctx = git__calloc(1, sizeof(git_patch_parse_ctx))) == NULL)
		return NULL;

	if (content_len) {
		if ((ctx->content = git__malloc(content_len)) == NULL)
			return NULL;

		memcpy((char *)ctx->content, content, content_len);
	}

	ctx->content_len = content_len;
	ctx->remain = ctx->content;
	ctx->remain_len = ctx->content_len;

	if (opts)
		memcpy(&ctx->opts, opts, sizeof(git_patch_options));
	else
		memcpy(&ctx->opts, &default_opts, sizeof(git_patch_options));

	GIT_REFCOUNT_INC(ctx);
	return ctx;
}
Beispiel #4
0
static git_diff_parsed *diff_parsed_alloc(void)
{
	git_diff_parsed *diff;

	if ((diff = git__calloc(1, sizeof(git_diff_parsed))) == NULL)
		return NULL;

	GIT_REFCOUNT_INC(diff);
	diff->base.type = GIT_DIFF_TYPE_PARSED;
	diff->base.strcomp = git__strcmp;
	diff->base.strncomp = git__strncmp;
	diff->base.pfxcomp = git__prefixcmp;
	diff->base.entrycomp = git_diff__entry_cmp;
	diff->base.patch_fn = git_patch_parsed_from_diff;
	diff->base.free_fn = diff_parsed_free;

	if (git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) {
		git__free(diff);
		return NULL;
	}

	diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;

	git_pool_init(&diff->base.pool, 1);

	if (git_vector_init(&diff->patches, 0, NULL) < 0 ||
		git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) {
		git_diff_free(&diff->base);
		return NULL;
	}

	git_vector_set_cmp(&diff->base.deltas, git_diff_delta__cmp);

	return diff;
}
Beispiel #5
0
static int submodule_get_or_create(git_submodule **out, git_repository *repo, git_strmap *map, const char *name)
{
	int error = 0;
	khiter_t pos;
	git_submodule *sm = NULL;

	pos = git_strmap_lookup_index(map, name);
	if (git_strmap_valid_index(map, pos)) {
		sm = git_strmap_value_at(map, pos);
		goto done;
	}

	/* if the submodule doesn't exist yet in the map, create it */
	if ((error = submodule_alloc(&sm, repo, name)) < 0)
		return error;

	pos = kh_put(str, map, sm->name, &error);
	/* nobody can beat us to adding it */
	assert(error != 0);
	if (error < 0) {
		git_submodule_free(sm);
		return error;
	}

	git_strmap_set_value_at(map, pos, sm);

done:
	GIT_REFCOUNT_INC(sm);
	*out = sm;
	return 0;
}
Beispiel #6
0
int git_attr_file__new(
	git_attr_file **out,
	git_attr_file_entry *entry,
	git_attr_file_source source)
{
	git_attr_file *attrs = git__calloc(1, sizeof(git_attr_file));
	GITERR_CHECK_ALLOC(attrs);

	if (git_mutex_init(&attrs->lock) < 0) {
		giterr_set(GITERR_OS, "Failed to initialize lock");
		git__free(attrs);
		return -1;
	}

	if (git_pool_init(&attrs->pool, 1, 0) < 0) {
		attr_file_free(attrs);
		return -1;
	}

	GIT_REFCOUNT_INC(attrs);
	attrs->entry  = entry;
	attrs->source = source;
	*out = attrs;
	return 0;
}
int git_repository_index(git_index **out, git_repository *repo)
{
	if (git_repository_index__weakptr(out, repo) < 0)
		return -1;

	GIT_REFCOUNT_INC(*out);
	return 0;
}
int git_repository_refdb(git_refdb **out, git_repository *repo)
{
	if (git_repository_refdb__weakptr(out, repo) < 0)
		return -1;

	GIT_REFCOUNT_INC(*out);
	return 0;
}
int git_repository_config(git_config **out, git_repository *repo)
{
	if (git_repository_config__weakptr(out, repo) < 0)
		return -1;

	GIT_REFCOUNT_INC(*out);
	return 0;
}
Beispiel #10
0
int git_refdb_write(git_refdb *db, git_reference *ref, int force)
{
	assert(db && db->backend);

	GIT_REFCOUNT_INC(db);
	ref->db = db;

	return db->backend->write(db->backend, ref, force);
}
Beispiel #11
0
void git_repository_set_odb(git_repository *repo, git_odb *odb)
{
	assert(repo && odb);

	drop_odb(repo);

	repo->_odb = odb;
	GIT_REFCOUNT_OWN(repo->_odb, repo);
	GIT_REFCOUNT_INC(odb);
}
Beispiel #12
0
void git_repository_set_index(git_repository *repo, git_index *index)
{
	assert(repo && index);

	drop_index(repo);

	repo->_index = index;
	GIT_REFCOUNT_OWN(repo->_index, repo);
	GIT_REFCOUNT_INC(index);
}
Beispiel #13
0
int git_rebase_inmemory_index(
	git_index **out,
	git_rebase *rebase)
{
	assert(out && rebase && rebase->index);

	GIT_REFCOUNT_INC(rebase->index);
	*out = rebase->index;

	return 0;
}
Beispiel #14
0
static void set_refdb(git_repository *repo, git_refdb *refdb)
{
	if (refdb) {
		GIT_REFCOUNT_OWN(refdb, repo);
		GIT_REFCOUNT_INC(refdb);
	}

	if ((refdb = (git_refdb*) git__swap(repo->_refdb, refdb)) != NULL) {
		GIT_REFCOUNT_OWN(refdb, NULL);
		git_refdb_free(refdb);
	}
}
Beispiel #15
0
static void set_index(git_repository *repo, git_index *index)
{
	if (index) {
		GIT_REFCOUNT_OWN(index, repo);
		GIT_REFCOUNT_INC(index);
	}

	if ((index = (git_index*) git__swap(repo->_index, index)) != NULL) {
		GIT_REFCOUNT_OWN(index, NULL);
		git_index_free(index);
	}
}
Beispiel #16
0
int git_refdb_iterator_next(git_reference **out, git_reference_iterator *iter)
{
	int error;

	if ((error = iter->next(out, iter)) < 0)
		return error;

	GIT_REFCOUNT_INC(iter->db);
	(*out)->db = iter->db;

	return 0;
}
Beispiel #17
0
int git_patch_parsed_from_diff(git_patch **out, git_diff *d, size_t idx)
{
	git_diff_parsed *diff = (git_diff_parsed *)d;
	git_patch *p;

	if ((p = git_vector_get(&diff->patches, idx)) == NULL)
		return -1;

	GIT_REFCOUNT_INC(p);
	*out = p;

	return 0;
}
Beispiel #18
0
/* Look up cache entry and file.
 * - If entry is not present, create it while the cache is locked.
 * - If file is present, increment refcount before returning it, so the
 *   cache can be unlocked and it won't go away.
 */
static int attr_cache_lookup(
	git_attr_file **out_file,
	git_attr_file_entry **out_entry,
	git_repository *repo,
	git_attr_session *attr_session,
	git_attr_file_source source,
	const char *base,
	const char *filename)
{
	int error = 0;
	git_buf path = GIT_BUF_INIT;
	const char *wd = git_repository_workdir(repo), *relfile;
	git_attr_cache *cache = git_repository_attr_cache(repo);
	git_attr_file_entry *entry = NULL;
	git_attr_file *file = NULL;

	/* join base and path as needed */
	if (base != NULL && git_path_root(filename) < 0) {
		git_buf *p = attr_session ? &attr_session->tmp : &path;

		if (git_buf_joinpath(p, base, filename) < 0)
			return -1;

		filename = p->ptr;
	}

	relfile = filename;
	if (wd && !git__prefixcmp(relfile, wd))
		relfile += strlen(wd);

	/* check cache for existing entry */
	if ((error = attr_cache_lock(cache)) < 0)
		goto cleanup;

	entry = attr_cache_lookup_entry(cache, relfile);
	if (!entry)
		error = attr_cache_make_entry(&entry, repo, relfile);
	else if (entry->file[source] != NULL) {
		file = entry->file[source];
		GIT_REFCOUNT_INC(file);
	}

	attr_cache_unlock(cache);

cleanup:
	*out_file  = file;
	*out_entry = entry;

	git_buf_free(&path);
	return error;
}
Beispiel #19
0
static void set_config(git_repository *repo, git_config *config)
{
	if (config) {
		GIT_REFCOUNT_OWN(config, repo);
		GIT_REFCOUNT_INC(config);
	}

	if ((config = (git_config*) git__swap(repo->_config, config)) != NULL) {
		GIT_REFCOUNT_OWN(config, NULL);
		git_config_free(config);
	}

	git_repository__cvar_cache_clear(repo);
}
Beispiel #20
0
int git_refdb_reflog_read(git_reflog **out, git_refdb *db,  const char *name)
{
	int error;

	assert(db && db->backend);

	if ((error = db->backend->reflog_read(out, db->backend, name)) < 0)
		return error;

	GIT_REFCOUNT_INC(db);
	(*out)->db = db;

	return 0;
}
Beispiel #21
0
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
{
	if (!db->backend || !db->backend->iterator) {
		giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators");
		return -1;
	}

	if (db->backend->iterator(out, db->backend, glob) < 0)
		return -1;

	GIT_REFCOUNT_INC(db);
	(*out)->db = db;

	return 0;
}
Beispiel #22
0
int git_refdb_new(git_refdb **out, git_repository *repo)
{
	git_refdb *db;

	assert(out && repo);

	db = git__calloc(1, sizeof(*db));
	GITERR_CHECK_ALLOC(db);

	db->repo = repo;

	*out = db;
	GIT_REFCOUNT_INC(db);
	return 0;
}
Beispiel #23
0
int git_odb_new(git_odb **out)
{
	git_odb *db = (git_odb*) git__calloc(1, sizeof(*db));
	GITERR_CHECK_ALLOC(db);

	if (git_cache_init(&db->own_cache) < 0 ||
		git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
		git__free(db);
		return -1;
	}

	*out = db;
	GIT_REFCOUNT_INC(db);
	return 0;
}
Beispiel #24
0
int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
{
	git_reference *ref;
	int error;

	assert(db && db->backend && out && ref_name);

	error = db->backend->lookup(&ref, db->backend, ref_name);
	if (error < 0)
		return error;

	GIT_REFCOUNT_INC(db);
	ref->db = db;

	*out = ref;
	return 0;
}
int git_sortedcache_new(
	git_sortedcache **out,
	size_t item_path_offset,
	git_sortedcache_free_item_fn free_item,
	void *free_item_payload,
	git_vector_cmp item_cmp,
	const char *path)
{
	git_sortedcache *sc;
	size_t pathlen;

	pathlen = path ? strlen(path) : 0;

	sc = (git_sortedcache *) git__calloc(sizeof(git_sortedcache) + pathlen + 1, 1);
	GITERR_CHECK_ALLOC(sc);

	if (git_pool_init(&sc->pool, 1, 0) < 0 ||
		git_vector_init(&sc->items, 4, item_cmp) < 0 ||
		git_strmap_alloc(&sc->map) < 0)
		goto fail;

	if (git_rwlock_init(&sc->lock)) {
		giterr_set(GITERR_OS, "Failed to initialize lock");
		goto fail;
	}

	sc->item_path_offset  = item_path_offset;
	sc->free_item         = free_item;
	sc->free_item_payload = free_item_payload;
	GIT_REFCOUNT_INC(sc);
	if (pathlen)
		memcpy(sc->path, path, pathlen);

	*out = sc;
	return 0;

fail:
	git_strmap_free(sc->map);
	git_vector_free(&sc->items);
	git_pool_clear(&sc->pool);
	git__free(sc);
	return -1;
}
Beispiel #26
0
int git_refdb_rename(
	git_reference **out,
	git_refdb *db,
	const char *old_name,
	const char *new_name,
	int force)
{
	int error;

	assert(db && db->backend);
	error = db->backend->rename(out, db->backend, old_name, new_name, force);
	if (error < 0)
		return error;

	if (out) {
		GIT_REFCOUNT_INC(db);
		(*out)->db = db;
	}

	return 0;
}
Beispiel #27
0
git_patch_parse_ctx *git_patch_parse_ctx_init(
	const char *content,
	size_t content_len,
	const git_patch_options *opts)
{
	git_patch_parse_ctx *ctx;
	git_patch_options default_opts = GIT_PATCH_OPTIONS_INIT;

	if ((ctx = git__calloc(1, sizeof(git_patch_parse_ctx))) == NULL)
		return NULL;

	if ((git_parse_ctx_init(&ctx->parse_ctx, content, content_len)) < 0) {
		git__free(ctx);
		return NULL;
	}

	if (opts)
		memcpy(&ctx->opts, opts, sizeof(git_patch_options));
	else
		memcpy(&ctx->opts, &default_opts, sizeof(git_patch_options));

	GIT_REFCOUNT_INC(ctx);
	return ctx;
}
Beispiel #28
0
/* insert entry or replace existing if we raced with another thread */
static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file)
{
	git_attr_file_entry *entry;
	git_attr_file *old;

	if (attr_cache_lock(cache) < 0)
		return -1;

	entry = attr_cache_lookup_entry(cache, file->entry->path);

	GIT_REFCOUNT_OWN(file, entry);
	GIT_REFCOUNT_INC(file);

	old = git__compare_and_swap(
		&entry->file[file->source], entry->file[file->source], file);

	if (old) {
		GIT_REFCOUNT_OWN(old, NULL);
		git_attr_file__free(old);
	}

	attr_cache_unlock(cache);
	return 0;
}
void git_sortedcache_incref(git_sortedcache *sc)
{
	GIT_REFCOUNT_INC(sc);
}
Beispiel #30
0
int git_diff_get_stats(
	git_diff_stats **out,
	git_diff *diff)
{
	size_t i, deltas;
	size_t total_insertions = 0, total_deletions = 0;
	git_diff_stats *stats = NULL;
	int error = 0;

	assert(out && diff);

	stats = git__calloc(1, sizeof(git_diff_stats));
	GITERR_CHECK_ALLOC(stats);

	deltas = git_diff_num_deltas(diff);

	stats->filestats = git__calloc(deltas, sizeof(diff_file_stats));
	if (!stats->filestats) {
		git__free(stats);
		return -1;
	}

	stats->diff = diff;
	GIT_REFCOUNT_INC(diff);

	for (i = 0; i < deltas && !error; ++i) {
		git_patch *patch = NULL;
		size_t add = 0, remove = 0, namelen;
		const git_diff_delta *delta;

		if ((error = git_patch_from_diff(&patch, diff, i)) < 0)
			break;

		/* keep a count of renames because it will affect formatting */
		delta = patch->delta;

		/* TODO ugh */
		namelen = strlen(delta->new_file.path);
		if (strcmp(delta->old_file.path, delta->new_file.path) != 0) {
			namelen += strlen(delta->old_file.path);
			stats->renames++;
		}

		/* and, of course, count the line stats */
		error = git_patch_line_stats(NULL, &add, &remove, patch);

		git_patch_free(patch);

		stats->filestats[i].insertions = add;
		stats->filestats[i].deletions = remove;

		total_insertions += add;
		total_deletions += remove;

		if (stats->max_name < namelen)
			stats->max_name = namelen;
		if (stats->max_filestat < add + remove)
			stats->max_filestat = add + remove;
	}

	stats->files_changed = deltas;
	stats->insertions = total_insertions;
	stats->deletions = total_deletions;
	stats->max_digits = digits_for_value(stats->max_filestat + 1);

	if (error < 0) {
		git_diff_stats_free(stats);
		stats = NULL;
	}

	*out = stats;
	return error;
}