示例#1
0
文件: update.c 项目: ChloeKo/libgit2
void test_object_tree_update__remove_all_entries(void)
{
	git_oid tree_index_id, tree_updater_id, base_id;
	git_tree *base_tree;
	git_index *idx;
	const char *path1 = "subdir/subdir2/README";
	const char *path2 = "subdir/subdir2/new.txt";

	git_tree_update updates[] = {
		{ GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB /* ignored */, path1},
		{ GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB /* ignored */, path2},
	};

	cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b"));
	cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id));

	/* Create it with an index */
	cl_git_pass(git_index_new(&idx));
	cl_git_pass(git_index_read_tree(idx, base_tree));
	cl_git_pass(git_index_remove(idx, path1, 0));
	cl_git_pass(git_index_remove(idx, path2, 0));
	cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo));
	git_index_free(idx);

	/* Perform the same operation via the tree updater */
	cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 2, updates));

	cl_assert_equal_oid(&tree_index_id, &tree_updater_id);

	git_tree_free(base_tree);
}
示例#2
0
文件: racy.c 项目: ethomson/libgit2
void test_index_racy__read_tree_clears_uptodate_bit(void)
{
	git_index *index;
	git_tree *tree;
	const git_index_entry *entry;
	git_oid id;

	setup_uptodate_files();

	cl_git_pass(git_repository_index(&index, g_repo));
	cl_git_pass(git_index_write_tree_to(&id, index, g_repo));
	cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
	cl_git_pass(git_index_read_tree(index, tree));

	/* ensure that no files are uptodate */
	cl_assert((entry = git_index_get_bypath(index, "A", 0)));
	cl_assert_equal_i(0, (entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE));

	cl_assert((entry = git_index_get_bypath(index, "B", 0)));
	cl_assert_equal_i(0, (entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE));

	cl_assert((entry = git_index_get_bypath(index, "C", 0)));
	cl_assert_equal_i(0, (entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE));

	git_tree_free(tree);
	git_index_free(index);
}
示例#3
0
文件: update.c 项目: ChloeKo/libgit2
void test_object_tree_update__replace_blob(void)
{
	git_oid tree_index_id, tree_updater_id, base_id;
	git_tree *base_tree;
	git_index *idx;
	const char *path = "README";
	git_index_entry entry = { {0} };

	git_tree_update updates[] = {
		{ GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, path},
	};

	cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b"));
	cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id));

	/* Create it with an index */
	cl_git_pass(git_index_new(&idx));
	cl_git_pass(git_index_read_tree(idx, base_tree));

	entry.path = path;
	cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92"));
	entry.mode = GIT_FILEMODE_BLOB;
	cl_git_pass(git_index_add(idx, &entry));

	cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo));
	git_index_free(idx);

	/* Perform the same operation via the tree updater */
	cl_git_pass(git_oid_fromstr(&updates[0].id, "fa49b077972391ad58037050f2a75f74e3671e92"));
	cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 1, updates));

	cl_assert_equal_oid(&tree_index_id, &tree_updater_id);

	git_tree_free(base_tree);
}
示例#4
0
ERL_NIF_TERM
geef_index_write_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	geef_index *index;
	geef_repository *repo;
	ErlNifBinary bin;
	git_oid id;
	int error;

	if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index))
		return enif_make_badarg(env);

	if (argc == 2) {
		if (!enif_get_resource(env, argv[1], geef_repository_type, (void **) &repo))
			return enif_make_badarg(env);

		error = git_index_write_tree_to(&id, index->index, repo->repo);
	} else {
		error = git_index_write_tree(&id, index->index);
	}

	if (error < 0)
		return geef_error(env);

	if (geef_oid_bin(&bin, &id) < 0)
		return geef_oom(env);

	return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin));
}
示例#5
0
文件: update.c 项目: ChloeKo/libgit2
void test_object_tree_update__add_blobs(void)
{
	git_oid tree_index_id, tree_updater_id, base_id;
	git_tree *base_tree;
	git_index *idx;
	git_index_entry entry = { {0} };
	int i;
	const char *paths[] = {
		"some/deep/path",
		"some/other/path",
		"a/path/elsewhere",
	};

	git_tree_update updates[] = {
		{ GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[0]},
		{ GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[1]},
		{ GIT_TREE_UPDATE_UPSERT, {{0}}, GIT_FILEMODE_BLOB, paths[2]},
	};

	cl_git_pass(git_oid_fromstr(&base_id, "c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b"));

	entry.mode = GIT_FILEMODE_BLOB;
	cl_git_pass(git_oid_fromstr(&entry.id, "fa49b077972391ad58037050f2a75f74e3671e92"));

	for (i = 0; i < 3; i++) {
		cl_git_pass(git_oid_fromstr(&updates[i].id, "fa49b077972391ad58037050f2a75f74e3671e92"));
	}

	for (i = 0; i < 2; i++) {
		int j;

		/* Create it with an index */
		cl_git_pass(git_index_new(&idx));

		base_tree = NULL;
		if (i == 1) {
			cl_git_pass(git_tree_lookup(&base_tree, g_repo, &base_id));
			cl_git_pass(git_index_read_tree(idx, base_tree));
		}

		for (j = 0; j < 3; j++) {
			entry.path = paths[j];
			cl_git_pass(git_index_add(idx, &entry));
		}

		cl_git_pass(git_index_write_tree_to(&tree_index_id, idx, g_repo));
		git_index_free(idx);

		/* Perform the same operations via the tree updater */
		cl_git_pass(git_tree_create_updated(&tree_updater_id, g_repo, base_tree, 3, updates));

		cl_assert_equal_oid(&tree_index_id, &tree_updater_id);
	}

	git_tree_free(base_tree);
}
示例#6
0
文件: nonetwork.c 项目: 1336/libgit2
void test_clone_nonetwork__clone_tag_to_tree(void)
{
	git_repository *stage;
	git_index_entry entry;
	git_index *index;
	git_odb *odb;
	git_oid tree_id;
	git_tree *tree;
	git_reference *tag;
	git_tree_entry *tentry;
	const char *file_path = "some/deep/path.txt";
	const char *file_content = "some content\n";
	const char *tag_name = "refs/tags/tree-tag";

	stage = cl_git_sandbox_init("testrepo.git");
	cl_git_pass(git_repository_odb(&odb, stage));
	cl_git_pass(git_index_new(&index));

	memset(&entry, 0, sizeof(git_index_entry));
	entry.path = file_path;
	entry.mode = GIT_FILEMODE_BLOB;
	cl_git_pass(git_odb_write(&entry.id, odb, file_content, strlen(file_content), GIT_OBJ_BLOB));

	cl_git_pass(git_index_add(index, &entry));
	cl_git_pass(git_index_write_tree_to(&tree_id, index, stage));
	cl_git_pass(git_reference_create(&tag, stage, tag_name, &tree_id, 0, NULL));
	git_reference_free(tag);
	git_odb_free(odb);
	git_index_free(index);

	g_options.local = GIT_CLONE_NO_LOCAL;
	cl_git_pass(git_clone(&g_repo, cl_git_path_url(git_repository_path(stage)), "./foo", &g_options));
	git_repository_free(stage);

	cl_git_pass(git_reference_lookup(&tag, g_repo, tag_name));
	cl_git_pass(git_tree_lookup(&tree, g_repo, git_reference_target(tag)));
	git_reference_free(tag);

	cl_git_pass(git_tree_entry_bypath(&tentry, tree, file_path));
	git_tree_entry_free(tentry);
	git_tree_free(tree);

	cl_fixture_cleanup("testrepo.git");
}
示例#7
0
文件: index.c 项目: flowroute/pygit2
PyObject *
Index_write_tree(Index *self, PyObject *args)
{
    git_oid oid;
    Repository *repo = NULL;
    int err;

    if (!PyArg_ParseTuple(args, "|O!", &RepositoryType, &repo))
        return NULL;

    if (repo)
        err = git_index_write_tree_to(&oid, self->index, repo->repo);
    else
        err = git_index_write_tree(&oid, self->index);

    if (err < 0)
        return Error_set(err);

    return git_oid_to_python(&oid);
}
示例#8
0
/*
 *  call-seq:
 *    index.write_tree([repo]) -> oid
 *
 *  Write the index to a tree, either in the index's repository, or in
 *  the given +repo+.
 *
 *  If the index contains any files in conflict, writing the tree will fail.
 *
 *  Returns the OID string of the written tree object.
 */
static VALUE rb_git_index_writetree(int argc, VALUE *argv, VALUE self)
{
	git_index *index;
	git_oid tree_oid;
	int error;
	VALUE rb_repo;

	Data_Get_Struct(self, git_index, index);

	if (rb_scan_args(argc, argv, "01", &rb_repo) == 1) {
		git_repository *repo = NULL;
		rugged_check_repo(rb_repo);
		Data_Get_Struct(rb_repo, git_repository, repo);
		error = git_index_write_tree_to(&tree_oid, index, repo);
	}
	else {
		error = git_index_write_tree(&tree_oid, index);
	}

	rugged_exception_check(error);
	return rugged_create_oid(&tree_oid);
}
示例#9
0
void test_index_read_index__read_and_writes(void)
{
	git_oid tree_id, new_tree_id;
	git_tree *tree;
	git_index *tree_index, *new_index;

	cl_git_pass(git_oid_fromstr(&tree_id, "ae90f12eea699729ed24555e40b9fd669da12a12"));
	cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
	cl_git_pass(git_index_new(&tree_index));
	cl_git_pass(git_index_read_tree(tree_index, tree));
	cl_git_pass(git_index_read_index(_index, tree_index));
	cl_git_pass(git_index_write(_index));

	cl_git_pass(git_index_open(&new_index, git_index_path(_index)));
	cl_git_pass(git_index_write_tree_to(&new_tree_id, new_index, _repo));

	cl_assert_equal_oid(&tree_id, &new_tree_id);

	git_tree_free(tree);
	git_index_free(tree_index);
	git_index_free(new_index);
}
示例#10
0
static int rebase_commit__create(
	git_commit **out,
	git_rebase *rebase,
	git_index *index,
	git_commit *parent_commit,
	const git_signature *author,
	const git_signature *committer,
	const char *message_encoding,
	const char *message)
{
	git_rebase_operation *operation;
	git_commit *current_commit = NULL, *commit = NULL;
	git_tree *parent_tree = NULL, *tree = NULL;
	git_oid tree_id, commit_id;
	int error;

	operation = git_array_get(rebase->operations, rebase->current);

	if (git_index_has_conflicts(index)) {
		giterr_set(GITERR_REBASE, "conflicts have not been resolved");
		error = GIT_EUNMERGED;
		goto done;
	}

	if ((error = git_commit_lookup(&current_commit, rebase->repo, &operation->id)) < 0 ||
		(error = git_commit_tree(&parent_tree, parent_commit)) < 0 ||
		(error = git_index_write_tree_to(&tree_id, index, rebase->repo)) < 0 ||
		(error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0)
		goto done;

	if (git_oid_equal(&tree_id, git_tree_id(parent_tree))) {
		giterr_set(GITERR_REBASE, "this patch has already been applied");
		error = GIT_EAPPLIED;
		goto done;
	}

	if (!author)
		author = git_commit_author(current_commit);

	if (!message) {
		message_encoding = git_commit_message_encoding(current_commit);
		message = git_commit_message(current_commit);
	}

	if ((error = git_commit_create(&commit_id, rebase->repo, NULL, author,
		committer, message_encoding, message, tree, 1,
		(const git_commit **)&parent_commit)) < 0 ||
		(error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0)
		goto done;

	*out = commit;

done:
	if (error < 0)
		git_commit_free(commit);

	git_commit_free(current_commit);
	git_tree_free(parent_tree);
	git_tree_free(tree);

	return error;
}
示例#11
0
static int try_to_git_merge(git_repository *repo, git_reference *local, git_reference *remote, git_oid *base, const git_oid *local_id, const git_oid *remote_id)
{
	git_tree *local_tree, *remote_tree, *base_tree;
	git_commit *local_commit, *remote_commit, *base_commit;
	git_index *merged_index;
	git_merge_options merge_options;

	if (verbose) {
		char outlocal[41], outremote[41];
		outlocal[40] = outremote[40] = 0;
		git_oid_fmt(outlocal, local_id);
		git_oid_fmt(outremote, remote_id);
		fprintf(stderr, "trying to merge local SHA %s remote SHA %s\n", outlocal, outremote);
	}

	git_merge_init_options(&merge_options, GIT_MERGE_OPTIONS_VERSION);
#ifdef USE_LIBGIT23_API
	merge_options.tree_flags = GIT_MERGE_TREE_FIND_RENAMES;
#else
	merge_options.flags = GIT_MERGE_TREE_FIND_RENAMES;
#endif
	merge_options.file_favor = GIT_MERGE_FILE_FAVOR_UNION;
	merge_options.rename_threshold = 100;
	if (git_commit_lookup(&local_commit, repo, local_id))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: can't get commit (%s)"), giterr_last()->message);
	if (git_commit_tree(&local_tree, local_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: failed local tree lookup (%s)"), giterr_last()->message);
	if (git_commit_lookup(&remote_commit, repo, remote_id))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: can't get commit (%s)"), giterr_last()->message);
	if (git_commit_tree(&remote_tree, remote_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: failed remote tree lookup (%s)"), giterr_last()->message);
	if (git_commit_lookup(&base_commit, repo, base))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: can't get commit: (%s)"), giterr_last()->message);
	if (git_commit_tree(&base_tree, base_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: failed base tree lookup: (%s)"), giterr_last()->message);
	if (git_merge_trees(&merged_index, repo, base_tree, local_tree, remote_tree, &merge_options))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge failed (%s)"), giterr_last()->message);
	if (git_index_has_conflicts(merged_index)) {
		int error;
		const git_index_entry *ancestor = NULL,
				*ours = NULL,
				*theirs = NULL;
		git_index_conflict_iterator *iter = NULL;
		error = git_index_conflict_iterator_new(&iter, merged_index);
		while (git_index_conflict_next(&ancestor, &ours, &theirs, iter)
		       != GIT_ITEROVER) {
			/* Mark this conflict as resolved */
			fprintf(stderr, "conflict in %s / %s / %s -- ",
				ours ? ours->path : "-",
				theirs ? theirs->path : "-",
				ancestor ? ancestor->path : "-");
			if ((!ours && theirs && ancestor) ||
			    (ours && !theirs && ancestor)) {
				// the file was removed on one side or the other - just remove it
				fprintf(stderr, "looks like a delete on one side; removing the file from the index\n");
				error = git_index_remove(merged_index, ours ? ours->path : theirs->path, GIT_INDEX_STAGE_ANY);
			} else {
				error = git_index_conflict_remove(merged_index, ours ? ours->path : theirs ? theirs->path : ancestor->path);
			}
			if (error) {
				fprintf(stderr, "error at conflict resplution (%s)", giterr_last()->message);
			}
		}
		git_index_conflict_cleanup(merged_index);
		git_index_conflict_iterator_free(iter);
		report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge conflict - manual intervention needed"));
	}
	git_oid merge_oid, commit_oid;
	git_tree *merged_tree;
	git_signature *author;
	git_commit *commit;

	if (git_index_write_tree_to(&merge_oid, merged_index, repo))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the tree failed (%s)"), giterr_last()->message);
	if (git_tree_lookup(&merged_tree, repo, &merge_oid))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: tree lookup failed (%s)"), giterr_last()->message);
	if (git_signature_default(&author, repo) < 0)
		return report_error(translate("gettextFromC", "Failed to get author: (%s)"), giterr_last()->message);
	if (git_commit_create_v(&commit_oid, repo, NULL, author, author, NULL, "automatic merge", merged_tree, 2, local_commit, remote_commit))
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: git commit create failed (%s)"), giterr_last()->message);
	if (git_commit_lookup(&commit, repo, &commit_oid))
		return report_error(translate("gettextFromC", "Error: could not lookup the merge commit I just created (%s)"), giterr_last()->message);
	if (git_branch_is_head(local) && !git_repository_is_bare(repo)) {
		git_object *parent;
		git_reference_peel(&parent, local, GIT_OBJ_COMMIT);
		if (update_git_checkout(repo, parent, merged_tree)) {
			report_error("Warning: checked out branch is inconsistent with git data");
		}
	}
	if (git_reference_set_target(&local, local, &commit_oid, "Subsurface merge event"))
		return report_error("Error: failed to update branch (%s)", giterr_last()->message);
	set_git_id(&commit_oid);
	git_signature_free(author);

	return 0;
}
示例#12
0
static int try_to_git_merge(git_repository *repo, git_reference **local_p, git_reference *remote, git_oid *base, const git_oid *local_id, const git_oid *remote_id)
{
	UNUSED(remote);
	git_tree *local_tree, *remote_tree, *base_tree;
	git_commit *local_commit, *remote_commit, *base_commit;
	git_index *merged_index;
	git_merge_options merge_options;

	if (verbose) {
		char outlocal[41], outremote[41];
		outlocal[40] = outremote[40] = 0;
		git_oid_fmt(outlocal, local_id);
		git_oid_fmt(outremote, remote_id);
		fprintf(stderr, "trying to merge local SHA %s remote SHA %s\n", outlocal, outremote);
	}

	git_merge_init_options(&merge_options, GIT_MERGE_OPTIONS_VERSION);
#if !LIBGIT2_VER_MAJOR && LIBGIT2_VER_MINOR > 23
	merge_options.flags = GIT_MERGE_FIND_RENAMES;
#else
	merge_options.tree_flags = GIT_MERGE_TREE_FIND_RENAMES;
#endif
	merge_options.file_favor = GIT_MERGE_FILE_FAVOR_UNION;
	merge_options.rename_threshold = 100;
	if (git_commit_lookup(&local_commit, repo, local_id)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: can't get commit (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_tree(&local_tree, local_commit)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: failed local tree lookup (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_lookup(&remote_commit, repo, remote_id)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: can't get commit (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_tree(&remote_tree, remote_commit)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: failed local tree lookup (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_lookup(&base_commit, repo, base)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: can't get commit (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_commit_tree(&base_tree, base_commit)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: failed base tree lookup (%s)", giterr_last()->message);
		goto diverged_error;
	}
	if (git_merge_trees(&merged_index, repo, base_tree, local_tree, remote_tree, &merge_options)) {
		fprintf(stderr, "Remote storage and local data diverged. Error: merge failed (%s)", giterr_last()->message);
		// this is the one where I want to report more detail to the user - can't quite explain why
		return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: merge failed (%s)"), giterr_last()->message);
	}
	if (git_index_has_conflicts(merged_index)) {
		int error;
		const git_index_entry *ancestor = NULL,
				*ours = NULL,
				*theirs = NULL;
		git_index_conflict_iterator *iter = NULL;
		error = git_index_conflict_iterator_new(&iter, merged_index);
		while (git_index_conflict_next(&ancestor, &ours, &theirs, iter)
		       != GIT_ITEROVER) {
			/* Mark this conflict as resolved */
			fprintf(stderr, "conflict in %s / %s / %s -- ",
				ours ? ours->path : "-",
				theirs ? theirs->path : "-",
				ancestor ? ancestor->path : "-");
			if ((!ours && theirs && ancestor) ||
			    (ours && !theirs && ancestor)) {
				// the file was removed on one side or the other - just remove it
				fprintf(stderr, "looks like a delete on one side; removing the file from the index\n");
				error = git_index_remove(merged_index, ours ? ours->path : theirs->path, GIT_INDEX_STAGE_ANY);
			} else if (ancestor) {
				error = git_index_conflict_remove(merged_index, ours ? ours->path : theirs ? theirs->path : ancestor->path);
			}
			if (error) {
				fprintf(stderr, "error at conflict resplution (%s)", giterr_last()->message);
			}
		}
		git_index_conflict_cleanup(merged_index);
		git_index_conflict_iterator_free(iter);
		report_error(translate("gettextFromC", "Remote storage and local data diverged. Cannot combine local and remote changes"));
	}
	git_oid merge_oid, commit_oid;
	git_tree *merged_tree;
	git_signature *author;
	git_commit *commit;

	if (git_index_write_tree_to(&merge_oid, merged_index, repo))
		goto write_error;
	if (git_tree_lookup(&merged_tree, repo, &merge_oid))
		goto write_error;
	if (git_signature_default(&author, repo) < 0)
		if (git_signature_now(&author, "Subsurface", "noemail@given") < 0)
			goto write_error;
	if (git_commit_create_v(&commit_oid, repo, NULL, author, author, NULL, "automatic merge", merged_tree, 2, local_commit, remote_commit))
		goto write_error;
	if (git_commit_lookup(&commit, repo, &commit_oid))
		goto write_error;
	if (git_branch_is_head(*local_p) && !git_repository_is_bare(repo)) {
		git_object *parent;
		git_reference_peel(&parent, *local_p, GIT_OBJ_COMMIT);
		if (update_git_checkout(repo, parent, merged_tree)) {
			goto write_error;
		}
	}
	if (git_reference_set_target(local_p, *local_p, &commit_oid, "Subsurface merge event"))
		goto write_error;
	set_git_id(&commit_oid);
	git_signature_free(author);
	if (verbose)
		fprintf(stderr, "Successfully merged repositories");
	return 0;

diverged_error:
	return report_error(translate("gettextFromC", "Remote storage and local data diverged"));

write_error:
	return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the data failed (%s)"), giterr_last()->message);
}