| /* |
| * dump_editor.c: The svn_delta_editor_t editor used by svnrdump to |
| * dump revisions. |
| * |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| */ |
| |
| #include "svn_types.h" |
| #include "svn_props.h" |
| #include "svn_ra.h" |
| #include "svn_io.h" |
| #include "svn_delta.h" |
| |
| #include "private/svn_repos_private.h" |
| #include "private/svn_editor.h" |
| |
| #include "svnrdump.h" |
| #include <assert.h> |
| |
| |
| /* The baton used by the dump editor. */ |
| struct dump_edit_baton { |
| /* A backdoor ra session to fetch additional information during the edit. */ |
| svn_ra_session_t *ra_session; |
| |
| /* The revision we're currently dumping. */ |
| svn_revnum_t current_revision; |
| }; |
| |
| static svn_error_t * |
| fetch_base_func(const char **filename, |
| void *baton, |
| const char *path, |
| svn_revnum_t base_revision, |
| apr_pool_t *result_pool, |
| apr_pool_t *scratch_pool) |
| { |
| struct dump_edit_baton *eb = baton; |
| svn_stream_t *fstream; |
| svn_error_t *err; |
| |
| if (path[0] == '/') |
| path += 1; |
| |
| if (! SVN_IS_VALID_REVNUM(base_revision)) |
| base_revision = eb->current_revision - 1; |
| |
| SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL, |
| svn_io_file_del_on_pool_cleanup, |
| result_pool, scratch_pool)); |
| |
| err = svn_ra_get_file(eb->ra_session, path, base_revision, |
| fstream, NULL, NULL, scratch_pool); |
| if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) |
| { |
| svn_error_clear(err); |
| SVN_ERR(svn_stream_close(fstream)); |
| |
| *filename = NULL; |
| return SVN_NO_ERROR; |
| } |
| else if (err) |
| return svn_error_trace(err); |
| |
| SVN_ERR(svn_stream_close(fstream)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| fetch_props_func(apr_hash_t **props, |
| void *baton, |
| const char *path, |
| svn_revnum_t base_revision, |
| apr_pool_t *result_pool, |
| apr_pool_t *scratch_pool) |
| { |
| struct dump_edit_baton *eb = baton; |
| svn_node_kind_t node_kind; |
| |
| if (path[0] == '/') |
| path += 1; |
| |
| if (! SVN_IS_VALID_REVNUM(base_revision)) |
| base_revision = eb->current_revision - 1; |
| |
| SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind, |
| scratch_pool)); |
| |
| if (node_kind == svn_node_file) |
| { |
| SVN_ERR(svn_ra_get_file(eb->ra_session, path, base_revision, |
| NULL, NULL, props, result_pool)); |
| } |
| else if (node_kind == svn_node_dir) |
| { |
| apr_array_header_t *tmp_props; |
| |
| SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path, |
| base_revision, 0 /* Dirent fields */, |
| result_pool)); |
| tmp_props = svn_prop_hash_to_array(*props, result_pool); |
| SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props, |
| result_pool)); |
| *props = svn_prop_array_to_hash(tmp_props, result_pool); |
| } |
| else |
| { |
| *props = apr_hash_make(result_pool); |
| } |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| fetch_kind_func(svn_node_kind_t *kind, |
| void *baton, |
| const char *path, |
| svn_revnum_t base_revision, |
| apr_pool_t *scratch_pool) |
| { |
| struct dump_edit_baton *eb = baton; |
| |
| if (path[0] == '/') |
| path += 1; |
| |
| if (! SVN_IS_VALID_REVNUM(base_revision)) |
| base_revision = eb->current_revision - 1; |
| |
| SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, kind, |
| scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| svn_error_t * |
| svn_rdump__get_dump_editor(const svn_delta_editor_t **editor, |
| void **edit_baton, |
| svn_revnum_t revision, |
| svn_stream_t *stream, |
| svn_ra_session_t *ra_session, |
| const char *update_anchor_relpath, |
| svn_cancel_func_t cancel_func, |
| void *cancel_baton, |
| apr_pool_t *pool) |
| { |
| struct dump_edit_baton *eb; |
| svn_delta_shim_callbacks_t *shim_callbacks = |
| svn_delta_shim_callbacks_default(pool); |
| |
| eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton)); |
| eb->ra_session = ra_session; |
| eb->current_revision = revision; |
| |
| SVN_ERR(svn_repos__get_dump_editor(editor, edit_baton, |
| stream, update_anchor_relpath, pool)); |
| |
| /* Wrap this editor in a cancellation editor. */ |
| SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton, |
| *editor, *edit_baton, |
| editor, edit_baton, |
| pool)); |
| |
| shim_callbacks->fetch_base_func = fetch_base_func; |
| shim_callbacks->fetch_props_func = fetch_props_func; |
| shim_callbacks->fetch_kind_func = fetch_kind_func; |
| shim_callbacks->fetch_baton = eb; |
| |
| SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton, |
| NULL, NULL, shim_callbacks, pool, pool)); |
| |
| return SVN_NO_ERROR; |
| } |