1/* 2 * debug_editor.c : An editor that writes the operations it does to stderr. 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24#include "svn_io.h" 25 26#include "debug_editor.h" 27 28struct edit_baton 29{ 30 const svn_delta_editor_t *wrapped_editor; 31 void *wrapped_edit_baton; 32 33 int indent_level; 34 35 svn_stream_t *out; 36}; 37 38struct dir_baton 39{ 40 void *edit_baton; 41 void *wrapped_dir_baton; 42}; 43 44struct file_baton 45{ 46 void *edit_baton; 47 void *wrapped_file_baton; 48}; 49 50static svn_error_t * 51write_indent(struct edit_baton *eb, apr_pool_t *pool) 52{ 53 int i; 54 55 /* This is DBG_FLAG from ../libsvn_subr/debug.c */ 56 SVN_ERR(svn_stream_puts(eb->out, "DBG:")); 57 for (i = 0; i < eb->indent_level; ++i) 58 SVN_ERR(svn_stream_puts(eb->out, " ")); 59 60 return SVN_NO_ERROR; 61} 62 63static svn_error_t * 64set_target_revision(void *edit_baton, 65 svn_revnum_t target_revision, 66 apr_pool_t *pool) 67{ 68 struct edit_baton *eb = edit_baton; 69 70 SVN_ERR(write_indent(eb, pool)); 71 SVN_ERR(svn_stream_printf(eb->out, pool, "set_target_revision : %ld\n", 72 target_revision)); 73 74 return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, 75 target_revision, 76 pool); 77} 78 79static svn_error_t * 80open_root(void *edit_baton, 81 svn_revnum_t base_revision, 82 apr_pool_t *pool, 83 void **root_baton) 84{ 85 struct edit_baton *eb = edit_baton; 86 struct dir_baton *dir_baton = apr_palloc(pool, sizeof(*dir_baton)); 87 88 SVN_ERR(write_indent(eb, pool)); 89 SVN_ERR(svn_stream_printf(eb->out, pool, "open_root : %ld\n", 90 base_revision)); 91 eb->indent_level++; 92 93 SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, 94 base_revision, 95 pool, 96 &dir_baton->wrapped_dir_baton)); 97 98 dir_baton->edit_baton = edit_baton; 99 100 *root_baton = dir_baton; 101 102 return SVN_NO_ERROR; 103} 104 105static svn_error_t * 106delete_entry(const char *path, 107 svn_revnum_t base_revision, 108 void *parent_baton, 109 apr_pool_t *pool) 110{ 111 struct dir_baton *pb = parent_baton; 112 struct edit_baton *eb = pb->edit_baton; 113 114 SVN_ERR(write_indent(eb, pool)); 115 SVN_ERR(svn_stream_printf(eb->out, pool, "delete_entry : %s:%ld\n", 116 path, base_revision)); 117 118 return eb->wrapped_editor->delete_entry(path, 119 base_revision, 120 pb->wrapped_dir_baton, 121 pool); 122} 123 124static svn_error_t * 125add_directory(const char *path, 126 void *parent_baton, 127 const char *copyfrom_path, 128 svn_revnum_t copyfrom_revision, 129 apr_pool_t *pool, 130 void **child_baton) 131{ 132 struct dir_baton *pb = parent_baton; 133 struct edit_baton *eb = pb->edit_baton; 134 struct dir_baton *b = apr_palloc(pool, sizeof(*b)); 135 136 SVN_ERR(write_indent(eb, pool)); 137 SVN_ERR(svn_stream_printf(eb->out, pool, 138 "add_directory : '%s' [from '%s':%ld]\n", 139 path, copyfrom_path, copyfrom_revision)); 140 eb->indent_level++; 141 142 SVN_ERR(eb->wrapped_editor->add_directory(path, 143 pb->wrapped_dir_baton, 144 copyfrom_path, 145 copyfrom_revision, 146 pool, 147 &b->wrapped_dir_baton)); 148 149 b->edit_baton = eb; 150 *child_baton = b; 151 152 return SVN_NO_ERROR; 153} 154 155static svn_error_t * 156open_directory(const char *path, 157 void *parent_baton, 158 svn_revnum_t base_revision, 159 apr_pool_t *pool, 160 void **child_baton) 161{ 162 struct dir_baton *pb = parent_baton; 163 struct edit_baton *eb = pb->edit_baton; 164 struct dir_baton *db = apr_palloc(pool, sizeof(*db)); 165 166 SVN_ERR(write_indent(eb, pool)); 167 SVN_ERR(svn_stream_printf(eb->out, pool, "open_directory : '%s':%ld\n", 168 path, base_revision)); 169 eb->indent_level++; 170 171 SVN_ERR(eb->wrapped_editor->open_directory(path, 172 pb->wrapped_dir_baton, 173 base_revision, 174 pool, 175 &db->wrapped_dir_baton)); 176 177 db->edit_baton = eb; 178 *child_baton = db; 179 180 return SVN_NO_ERROR; 181} 182 183static svn_error_t * 184add_file(const char *path, 185 void *parent_baton, 186 const char *copyfrom_path, 187 svn_revnum_t copyfrom_revision, 188 apr_pool_t *pool, 189 void **file_baton) 190{ 191 struct dir_baton *pb = parent_baton; 192 struct edit_baton *eb = pb->edit_baton; 193 struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); 194 195 SVN_ERR(write_indent(eb, pool)); 196 SVN_ERR(svn_stream_printf(eb->out, pool, 197 "add_file : '%s' [from '%s':%ld]\n", 198 path, copyfrom_path, copyfrom_revision)); 199 200 eb->indent_level++; 201 202 SVN_ERR(eb->wrapped_editor->add_file(path, 203 pb->wrapped_dir_baton, 204 copyfrom_path, 205 copyfrom_revision, 206 pool, 207 &fb->wrapped_file_baton)); 208 209 fb->edit_baton = eb; 210 *file_baton = fb; 211 212 return SVN_NO_ERROR; 213} 214 215static svn_error_t * 216open_file(const char *path, 217 void *parent_baton, 218 svn_revnum_t base_revision, 219 apr_pool_t *pool, 220 void **file_baton) 221{ 222 struct dir_baton *pb = parent_baton; 223 struct edit_baton *eb = pb->edit_baton; 224 struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); 225 226 SVN_ERR(write_indent(eb, pool)); 227 SVN_ERR(svn_stream_printf(eb->out, pool, "open_file : '%s':%ld\n", 228 path, base_revision)); 229 230 eb->indent_level++; 231 232 SVN_ERR(eb->wrapped_editor->open_file(path, 233 pb->wrapped_dir_baton, 234 base_revision, 235 pool, 236 &fb->wrapped_file_baton)); 237 238 fb->edit_baton = eb; 239 *file_baton = fb; 240 241 return SVN_NO_ERROR; 242} 243 244static svn_error_t * 245apply_textdelta(void *file_baton, 246 const char *base_checksum, 247 apr_pool_t *pool, 248 svn_txdelta_window_handler_t *handler, 249 void **handler_baton) 250{ 251 struct file_baton *fb = file_baton; 252 struct edit_baton *eb = fb->edit_baton; 253 254 SVN_ERR(write_indent(eb, pool)); 255 SVN_ERR(svn_stream_printf(eb->out, pool, "apply_textdelta : %s\n", 256 base_checksum)); 257 258 SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton, 259 base_checksum, 260 pool, 261 handler, 262 handler_baton)); 263 264 return SVN_NO_ERROR; 265} 266 267static svn_error_t * 268close_file(void *file_baton, 269 const char *text_checksum, 270 apr_pool_t *pool) 271{ 272 struct file_baton *fb = file_baton; 273 struct edit_baton *eb = fb->edit_baton; 274 275 eb->indent_level--; 276 277 SVN_ERR(write_indent(eb, pool)); 278 SVN_ERR(svn_stream_printf(eb->out, pool, "close_file : %s\n", 279 text_checksum)); 280 281 SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton, 282 text_checksum, pool)); 283 284 return SVN_NO_ERROR; 285} 286 287static svn_error_t * 288absent_file(const char *path, 289 void *file_baton, 290 apr_pool_t *pool) 291{ 292 struct file_baton *fb = file_baton; 293 struct edit_baton *eb = fb->edit_baton; 294 295 SVN_ERR(write_indent(eb, pool)); 296 SVN_ERR(svn_stream_printf(eb->out, pool, "absent_file : %s\n", path)); 297 298 SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton, 299 pool)); 300 301 return SVN_NO_ERROR; 302} 303 304static svn_error_t * 305close_directory(void *dir_baton, 306 apr_pool_t *pool) 307{ 308 struct dir_baton *db = dir_baton; 309 struct edit_baton *eb = db->edit_baton; 310 311 eb->indent_level--; 312 SVN_ERR(write_indent(eb, pool)); 313 SVN_ERR(svn_stream_printf(eb->out, pool, "close_directory\n")); 314 315 SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton, 316 pool)); 317 318 return SVN_NO_ERROR; 319} 320 321static svn_error_t * 322absent_directory(const char *path, 323 void *dir_baton, 324 apr_pool_t *pool) 325{ 326 struct dir_baton *db = dir_baton; 327 struct edit_baton *eb = db->edit_baton; 328 329 SVN_ERR(write_indent(eb, pool)); 330 SVN_ERR(svn_stream_printf(eb->out, pool, "absent_directory : %s\n", 331 path)); 332 333 SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton, 334 pool)); 335 336 return SVN_NO_ERROR; 337} 338 339static svn_error_t * 340change_file_prop(void *file_baton, 341 const char *name, 342 const svn_string_t *value, 343 apr_pool_t *pool) 344{ 345 struct file_baton *fb = file_baton; 346 struct edit_baton *eb = fb->edit_baton; 347 348 SVN_ERR(write_indent(eb, pool)); 349 SVN_ERR(svn_stream_printf(eb->out, pool, "change_file_prop : %s\n", 350 name)); 351 352 SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton, 353 name, 354 value, 355 pool)); 356 357 return SVN_NO_ERROR; 358} 359 360static svn_error_t * 361change_dir_prop(void *dir_baton, 362 const char *name, 363 const svn_string_t *value, 364 apr_pool_t *pool) 365{ 366 struct dir_baton *db = dir_baton; 367 struct edit_baton *eb = db->edit_baton; 368 369 SVN_ERR(write_indent(eb, pool)); 370 SVN_ERR(svn_stream_printf(eb->out, pool, "change_dir_prop : %s\n", name)); 371 372 SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton, 373 name, 374 value, 375 pool)); 376 377 return SVN_NO_ERROR; 378} 379 380static svn_error_t * 381close_edit(void *edit_baton, 382 apr_pool_t *pool) 383{ 384 struct edit_baton *eb = edit_baton; 385 386 SVN_ERR(write_indent(eb, pool)); 387 SVN_ERR(svn_stream_printf(eb->out, pool, "close_edit\n")); 388 389 SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool)); 390 391 return SVN_NO_ERROR; 392} 393 394svn_error_t * 395svn_delta__get_debug_editor(const svn_delta_editor_t **editor, 396 void **edit_baton, 397 const svn_delta_editor_t *wrapped_editor, 398 void *wrapped_edit_baton, 399 apr_pool_t *pool) 400{ 401 svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool); 402 struct edit_baton *eb = apr_palloc(pool, sizeof(*eb)); 403 apr_file_t *errfp; 404 svn_stream_t *out; 405 406 apr_status_t apr_err = apr_file_open_stderr(&errfp, pool); 407 if (apr_err) 408 return svn_error_wrap_apr(apr_err, "Problem opening stderr"); 409 410 out = svn_stream_from_aprfile2(errfp, TRUE, pool); 411 412 tree_editor->set_target_revision = set_target_revision; 413 tree_editor->open_root = open_root; 414 tree_editor->delete_entry = delete_entry; 415 tree_editor->add_directory = add_directory; 416 tree_editor->open_directory = open_directory; 417 tree_editor->change_dir_prop = change_dir_prop; 418 tree_editor->close_directory = close_directory; 419 tree_editor->absent_directory = absent_directory; 420 tree_editor->add_file = add_file; 421 tree_editor->open_file = open_file; 422 tree_editor->apply_textdelta = apply_textdelta; 423 tree_editor->change_file_prop = change_file_prop; 424 tree_editor->close_file = close_file; 425 tree_editor->absent_file = absent_file; 426 tree_editor->close_edit = close_edit; 427 428 eb->wrapped_editor = wrapped_editor; 429 eb->wrapped_edit_baton = wrapped_edit_baton; 430 eb->out = out; 431 eb->indent_level = 0; 432 433 *editor = tree_editor; 434 *edit_baton = eb; 435 436 return SVN_NO_ERROR; 437} 438