/*** From dir-delta.c ***/ svn_error_t * svn_repos_dir_delta(svn_fs_root_t *src_root, const char *src_parent_dir, const char *src_entry, svn_fs_root_t *tgt_root, const char *tgt_fullpath, const svn_delta_editor_t *editor, void *edit_baton, svn_repos_authz_func_t authz_read_func, void *authz_read_baton, svn_boolean_t text_deltas, svn_boolean_t recurse, svn_boolean_t entry_props, svn_boolean_t ignore_ancestry, apr_pool_t *pool) { return svn_repos_dir_delta2(src_root, src_parent_dir, src_entry, tgt_root, tgt_fullpath, editor, edit_baton, authz_read_func, authz_read_baton, text_deltas, SVN_DEPTH_INFINITY_OR_FILES(recurse), entry_props, ignore_ancestry, pool); }
/* The main dumper. */ svn_error_t * svn_repos_dump_fs3(svn_repos_t *repos, svn_stream_t *stream, svn_revnum_t start_rev, svn_revnum_t end_rev, svn_boolean_t incremental, svn_boolean_t use_deltas, svn_repos_notify_func_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { const svn_delta_editor_t *dump_editor; void *dump_edit_baton = NULL; svn_revnum_t i; svn_fs_t *fs = svn_repos_fs(repos); apr_pool_t *subpool = svn_pool_create(pool); svn_revnum_t youngest; const char *uuid; int version; svn_boolean_t found_old_reference = FALSE; svn_boolean_t found_old_mergeinfo = FALSE; svn_repos_notify_t *notify; /* Determine the current youngest revision of the filesystem. */ SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); /* Use default vals if necessary. */ if (! SVN_IS_VALID_REVNUM(start_rev)) start_rev = 0; if (! SVN_IS_VALID_REVNUM(end_rev)) end_rev = youngest; if (! stream) stream = svn_stream_empty(pool); /* Validate the revisions. */ if (start_rev > end_rev) return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, _("Start revision %ld" " is greater than end revision %ld"), start_rev, end_rev); if (end_rev > youngest) return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, _("End revision %ld is invalid " "(youngest revision is %ld)"), end_rev, youngest); if ((start_rev == 0) && incremental) incremental = FALSE; /* revision 0 looks the same regardless of whether or not this is an incremental dump, so just simplify things. */ /* Write out the UUID. */ SVN_ERR(svn_fs_get_uuid(fs, &uuid, pool)); /* If we're not using deltas, use the previous version, for compatibility with svn 1.0.x. */ version = SVN_REPOS_DUMPFILE_FORMAT_VERSION; if (!use_deltas) version--; /* Write out "general" metadata for the dumpfile. In this case, a magic header followed by a dumpfile format version. */ SVN_ERR(svn_stream_printf(stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", version)); SVN_ERR(svn_stream_printf(stream, pool, SVN_REPOS_DUMPFILE_UUID ": %s\n\n", uuid)); /* Create a notify object that we can reuse in the loop. */ if (notify_func) notify = svn_repos_notify_create(svn_repos_notify_dump_rev_end, pool); /* Main loop: we're going to dump revision i. */ for (i = start_rev; i <= end_rev; i++) { svn_revnum_t from_rev, to_rev; svn_fs_root_t *to_root; svn_boolean_t use_deltas_for_rev; svn_pool_clear(subpool); /* Check for cancellation. */ if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); /* Special-case the initial revision dump: it needs to contain *all* nodes, because it's the foundation of all future revisions in the dumpfile. */ if ((i == start_rev) && (! incremental)) { /* Special-special-case a dump of revision 0. */ if (i == 0) { /* Just write out the one revision 0 record and move on. The parser might want to use its properties. */ SVN_ERR(write_revision_record(stream, fs, 0, subpool)); to_rev = 0; goto loop_end; } /* Compare START_REV to revision 0, so that everything appears to be added. */ from_rev = 0; to_rev = i; } else { /* In the normal case, we want to compare consecutive revs. */ from_rev = i - 1; to_rev = i; } /* Write the revision record. */ SVN_ERR(write_revision_record(stream, fs, to_rev, subpool)); /* Fetch the editor which dumps nodes to a file. Regardless of what we've been told, don't use deltas for the first rev of a non-incremental dump. */ use_deltas_for_rev = use_deltas && (incremental || i != start_rev); SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton, fs, to_rev, "", stream, notify_func, notify_baton, start_rev, use_deltas_for_rev, FALSE, subpool)); /* Drive the editor in one way or another. */ SVN_ERR(svn_fs_revision_root(&to_root, fs, to_rev, subpool)); /* If this is the first revision of a non-incremental dump, we're in for a full tree dump. Otherwise, we want to simply replay the revision. */ if ((i == start_rev) && (! incremental)) { svn_fs_root_t *from_root; SVN_ERR(svn_fs_revision_root(&from_root, fs, from_rev, subpool)); SVN_ERR(svn_repos_dir_delta2(from_root, "", "", to_root, "", dump_editor, dump_edit_baton, NULL, NULL, FALSE, /* don't send text-deltas */ svn_depth_infinity, FALSE, /* don't send entry props */ FALSE, /* don't ignore ancestry */ subpool)); } else { SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE, dump_editor, dump_edit_baton, NULL, NULL, subpool)); } loop_end: if (notify_func) { notify->revision = to_rev; notify_func(notify_baton, notify, subpool); } if (dump_edit_baton) /* We never get an edit baton for r0. */ { if (((struct edit_baton *)dump_edit_baton)->found_old_reference) found_old_reference = TRUE; if (((struct edit_baton *)dump_edit_baton)->found_old_mergeinfo) found_old_mergeinfo = TRUE; } } if (notify_func) { /* Did we issue any warnings about references to revisions older than the oldest dumped revision? If so, then issue a final generic warning, since the inline warnings already issued might easily be missed. */ notify = svn_repos_notify_create(svn_repos_notify_dump_end, subpool); notify_func(notify_baton, notify, subpool); if (found_old_reference) { notify = svn_repos_notify_create(svn_repos_notify_warning, subpool); notify->warning = svn_repos_notify_warning_found_old_reference; notify->warning_str = _("The range of revisions dumped " "contained references to " "copy sources outside that " "range."); notify_func(notify_baton, notify, subpool); } /* Ditto if we issued any warnings about old revisions referenced in dumped mergeinfo. */ if (found_old_mergeinfo) { notify = svn_repos_notify_create(svn_repos_notify_warning, subpool); notify->warning = svn_repos_notify_warning_found_old_mergeinfo; notify->warning_str = _("The range of revisions dumped " "contained mergeinfo " "which reference revisions outside " "that range."); notify_func(notify_baton, notify, subpool); } } svn_pool_destroy(subpool); return SVN_NO_ERROR; }