static void test_trees_nofree(struct dsync_mailbox_tree *tree1,
			      struct dsync_mailbox_tree **_tree2)
{
	struct dsync_mailbox_tree *tree2 = *_tree2;
	struct dsync_mailbox_tree *orig_tree1, *orig_tree2;
	struct dsync_mailbox_tree_sync_ctx *ctx;
	struct dsync_mailbox_node *dup_node1, *dup_node2;
	const struct dsync_mailbox_tree_sync_change *change;

	orig_tree1 = dsync_mailbox_tree_dup(tree1);
	orig_tree2 = dsync_mailbox_tree_dup(tree2);

	/* test tree1 -> tree2 */
	dsync_mailbox_tree_build_guid_hash(tree1, &dup_node1, &dup_node2);
	dsync_mailbox_tree_build_guid_hash(tree2, &dup_node1, &dup_node2);
	ctx = dsync_mailbox_trees_sync_init(tree1, tree2,
					    DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY, 0);
	while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
	}
	dsync_mailbox_trees_sync_deinit(&ctx);
	test_tree_fixup(tree1);
	test_tree_fixup(tree2);
	if (!dsync_mailbox_trees_equal(tree1, tree2)) {
		test_assert(FALSE);
		trees_dump(tree1, tree2);
	}

	/* test tree2 -> tree1 */
	dsync_mailbox_tree_build_guid_hash(orig_tree1, &dup_node1, &dup_node2);
	dsync_mailbox_tree_build_guid_hash(orig_tree2, &dup_node1, &dup_node2);
	ctx = dsync_mailbox_trees_sync_init(orig_tree2, orig_tree1,
					    DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY, 0);
	while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
	}
	dsync_mailbox_trees_sync_deinit(&ctx);
	test_tree_fixup(orig_tree1);
	test_tree_fixup(orig_tree2);
	if (!dsync_mailbox_trees_equal(orig_tree1, orig_tree2)) {
		test_assert(FALSE);
		trees_dump(orig_tree1, orig_tree2);
	}

	/* make sure both directions produced equal trees */
	if (!dsync_mailbox_trees_equal(tree1, orig_tree1)) {
		test_assert(FALSE);
		trees_dump(tree1, orig_tree1);
	}

	dsync_mailbox_tree_deinit(_tree2);
	dsync_mailbox_tree_deinit(&orig_tree1);
	dsync_mailbox_tree_deinit(&orig_tree2);
}
static void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
{
	struct dsync_mailbox_tree_sync_ctx *ctx;
	const struct dsync_mailbox_tree_sync_change *change;
	enum dsync_mailbox_trees_sync_type sync_type;
	enum dsync_mailbox_trees_sync_flags sync_flags =
		(brain->debug ? DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG : 0) |
		(brain->master_brain ? DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN : 0);

	if (brain->no_backup_overwrite)
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
	else if (brain->backup_send)
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL;
	else if (brain->backup_recv)
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE;
	else
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;

	ctx = dsync_mailbox_trees_sync_init(brain->local_mailbox_tree,
					    brain->remote_mailbox_tree,
					    sync_type, sync_flags);
	while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
		if (dsync_brain_mailbox_tree_sync_change(brain, change,
							 &brain->mail_error) < 0) {
			brain->failed = TRUE;
			break;
		}
	}
	dsync_mailbox_trees_sync_deinit(&ctx);
}
static void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
{
	struct dsync_mailbox_tree_sync_ctx *ctx;
	const struct dsync_mailbox_tree_sync_change *change;
	enum dsync_mailbox_trees_sync_type sync_type;

	if (brain->no_backup_overwrite)
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
	else if (brain->backup_send)
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL;
	else if (brain->backup_recv)
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE;
	else
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;

	ctx = dsync_mailbox_trees_sync_init(brain->local_mailbox_tree,
					    brain->remote_mailbox_tree,
					    sync_type);
	while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
		if (dsync_brain_mailbox_tree_sync_change(brain, change) < 0)
			brain->failed = TRUE;
	}
	dsync_mailbox_trees_sync_deinit(&ctx);
}