1/* 2 * dump_editor.c: The svn_delta_editor_t editor used by svnrdump to 3 * dump revisions. 4 * 5 * ==================================================================== 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 * ==================================================================== 23 */ 24 25#include "svn_types.h" 26#include "svn_props.h" 27#include "svn_ra.h" 28#include "svn_io.h" 29#include "svn_delta.h" 30 31#include "private/svn_repos_private.h" 32#include "private/svn_editor.h" 33 34#include "svnrdump.h" 35#include <assert.h> 36 37 38/* The baton used by the dump editor. */ 39struct dump_edit_baton { 40 /* A backdoor ra session to fetch additional information during the edit. */ 41 svn_ra_session_t *ra_session; 42 43 /* The revision we're currently dumping. */ 44 svn_revnum_t current_revision; 45}; 46 47static svn_error_t * 48fetch_base_func(const char **filename, 49 void *baton, 50 const char *path, 51 svn_revnum_t base_revision, 52 apr_pool_t *result_pool, 53 apr_pool_t *scratch_pool) 54{ 55 struct dump_edit_baton *eb = baton; 56 svn_stream_t *fstream; 57 svn_error_t *err; 58 59 if (path[0] == '/') 60 path += 1; 61 62 if (! SVN_IS_VALID_REVNUM(base_revision)) 63 base_revision = eb->current_revision - 1; 64 65 SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL, 66 svn_io_file_del_on_pool_cleanup, 67 result_pool, scratch_pool)); 68 69 err = svn_ra_get_file(eb->ra_session, path, base_revision, 70 fstream, NULL, NULL, scratch_pool); 71 if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) 72 { 73 svn_error_clear(err); 74 SVN_ERR(svn_stream_close(fstream)); 75 76 *filename = NULL; 77 return SVN_NO_ERROR; 78 } 79 else if (err) 80 return svn_error_trace(err); 81 82 SVN_ERR(svn_stream_close(fstream)); 83 84 return SVN_NO_ERROR; 85} 86 87static svn_error_t * 88fetch_props_func(apr_hash_t **props, 89 void *baton, 90 const char *path, 91 svn_revnum_t base_revision, 92 apr_pool_t *result_pool, 93 apr_pool_t *scratch_pool) 94{ 95 struct dump_edit_baton *eb = baton; 96 svn_node_kind_t node_kind; 97 98 if (path[0] == '/') 99 path += 1; 100 101 if (! SVN_IS_VALID_REVNUM(base_revision)) 102 base_revision = eb->current_revision - 1; 103 104 SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind, 105 scratch_pool)); 106 107 if (node_kind == svn_node_file) 108 { 109 SVN_ERR(svn_ra_get_file(eb->ra_session, path, base_revision, 110 NULL, NULL, props, result_pool)); 111 } 112 else if (node_kind == svn_node_dir) 113 { 114 apr_array_header_t *tmp_props; 115 116 SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path, 117 base_revision, 0 /* Dirent fields */, 118 result_pool)); 119 tmp_props = svn_prop_hash_to_array(*props, result_pool); 120 SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props, 121 result_pool)); 122 *props = svn_prop_array_to_hash(tmp_props, result_pool); 123 } 124 else 125 { 126 *props = apr_hash_make(result_pool); 127 } 128 129 return SVN_NO_ERROR; 130} 131 132static svn_error_t * 133fetch_kind_func(svn_node_kind_t *kind, 134 void *baton, 135 const char *path, 136 svn_revnum_t base_revision, 137 apr_pool_t *scratch_pool) 138{ 139 struct dump_edit_baton *eb = baton; 140 141 if (path[0] == '/') 142 path += 1; 143 144 if (! SVN_IS_VALID_REVNUM(base_revision)) 145 base_revision = eb->current_revision - 1; 146 147 SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, kind, 148 scratch_pool)); 149 150 return SVN_NO_ERROR; 151} 152 153svn_error_t * 154svn_rdump__get_dump_editor(const svn_delta_editor_t **editor, 155 void **edit_baton, 156 svn_revnum_t revision, 157 svn_stream_t *stream, 158 svn_ra_session_t *ra_session, 159 const char *update_anchor_relpath, 160 svn_cancel_func_t cancel_func, 161 void *cancel_baton, 162 apr_pool_t *pool) 163{ 164 struct dump_edit_baton *eb; 165 svn_delta_shim_callbacks_t *shim_callbacks = 166 svn_delta_shim_callbacks_default(pool); 167 168 eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton)); 169 eb->ra_session = ra_session; 170 eb->current_revision = revision; 171 172 SVN_ERR(svn_repos__get_dump_editor(editor, edit_baton, 173 stream, update_anchor_relpath, pool)); 174 175 /* Wrap this editor in a cancellation editor. */ 176 SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton, 177 *editor, *edit_baton, 178 editor, edit_baton, 179 pool)); 180 181 shim_callbacks->fetch_base_func = fetch_base_func; 182 shim_callbacks->fetch_props_func = fetch_props_func; 183 shim_callbacks->fetch_kind_func = fetch_kind_func; 184 shim_callbacks->fetch_baton = eb; 185 186 SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton, 187 NULL, NULL, shim_callbacks, pool, pool)); 188 189 return SVN_NO_ERROR; 190} 191