debug_editor.c revision 362181
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 "private/svn_delta_private.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 const char *prefix; 37}; 38 39struct dir_baton 40{ 41 void *edit_baton; 42 void *wrapped_dir_baton; 43}; 44 45struct file_baton 46{ 47 void *edit_baton; 48 void *wrapped_file_baton; 49}; 50 51static svn_error_t * 52write_indent(struct edit_baton *eb, apr_pool_t *pool) 53{ 54 int i; 55 56 SVN_ERR(svn_stream_puts(eb->out, eb->prefix)); 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 if (eb->wrapped_editor) 75 SVN_ERR(eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, 76 target_revision, 77 pool)); 78 return SVN_NO_ERROR; 79} 80 81static svn_error_t * 82open_root(void *edit_baton, 83 svn_revnum_t base_revision, 84 apr_pool_t *pool, 85 void **root_baton) 86{ 87 struct edit_baton *eb = edit_baton; 88 struct dir_baton *dir_baton = apr_palloc(pool, sizeof(*dir_baton)); 89 90 SVN_ERR(write_indent(eb, pool)); 91 SVN_ERR(svn_stream_printf(eb->out, pool, "open_root : %ld\n", 92 base_revision)); 93 eb->indent_level++; 94 95 if (eb->wrapped_editor) 96 SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, 97 base_revision, 98 pool, 99 &dir_baton->wrapped_dir_baton)); 100 101 dir_baton->edit_baton = edit_baton; 102 103 *root_baton = dir_baton; 104 105 return SVN_NO_ERROR; 106} 107 108static svn_error_t * 109delete_entry(const char *path, 110 svn_revnum_t base_revision, 111 void *parent_baton, 112 apr_pool_t *pool) 113{ 114 struct dir_baton *pb = parent_baton; 115 struct edit_baton *eb = pb->edit_baton; 116 117 SVN_ERR(write_indent(eb, pool)); 118 SVN_ERR(svn_stream_printf(eb->out, pool, "delete_entry : %s:%ld\n", 119 path, base_revision)); 120 121 if (eb->wrapped_editor) 122 SVN_ERR(eb->wrapped_editor->delete_entry(path, 123 base_revision, 124 pb->wrapped_dir_baton, 125 pool)); 126 return SVN_NO_ERROR; 127} 128 129static svn_error_t * 130add_directory(const char *path, 131 void *parent_baton, 132 const char *copyfrom_path, 133 svn_revnum_t copyfrom_revision, 134 apr_pool_t *pool, 135 void **child_baton) 136{ 137 struct dir_baton *pb = parent_baton; 138 struct edit_baton *eb = pb->edit_baton; 139 struct dir_baton *b = apr_palloc(pool, sizeof(*b)); 140 141 SVN_ERR(write_indent(eb, pool)); 142 SVN_ERR(svn_stream_printf(eb->out, pool, 143 "add_directory : '%s' [from '%s':%ld]\n", 144 path, copyfrom_path, copyfrom_revision)); 145 eb->indent_level++; 146 147 if (eb->wrapped_editor) 148 SVN_ERR(eb->wrapped_editor->add_directory(path, 149 pb->wrapped_dir_baton, 150 copyfrom_path, 151 copyfrom_revision, 152 pool, 153 &b->wrapped_dir_baton)); 154 155 b->edit_baton = eb; 156 *child_baton = b; 157 158 return SVN_NO_ERROR; 159} 160 161static svn_error_t * 162open_directory(const char *path, 163 void *parent_baton, 164 svn_revnum_t base_revision, 165 apr_pool_t *pool, 166 void **child_baton) 167{ 168 struct dir_baton *pb = parent_baton; 169 struct edit_baton *eb = pb->edit_baton; 170 struct dir_baton *db = apr_palloc(pool, sizeof(*db)); 171 172 SVN_ERR(write_indent(eb, pool)); 173 SVN_ERR(svn_stream_printf(eb->out, pool, "open_directory : '%s':%ld\n", 174 path, base_revision)); 175 eb->indent_level++; 176 177 if (eb->wrapped_editor) 178 SVN_ERR(eb->wrapped_editor->open_directory(path, 179 pb->wrapped_dir_baton, 180 base_revision, 181 pool, 182 &db->wrapped_dir_baton)); 183 184 db->edit_baton = eb; 185 *child_baton = db; 186 187 return SVN_NO_ERROR; 188} 189 190static svn_error_t * 191add_file(const char *path, 192 void *parent_baton, 193 const char *copyfrom_path, 194 svn_revnum_t copyfrom_revision, 195 apr_pool_t *pool, 196 void **file_baton) 197{ 198 struct dir_baton *pb = parent_baton; 199 struct edit_baton *eb = pb->edit_baton; 200 struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); 201 202 SVN_ERR(write_indent(eb, pool)); 203 SVN_ERR(svn_stream_printf(eb->out, pool, 204 "add_file : '%s' [from '%s':%ld]\n", 205 path, copyfrom_path, copyfrom_revision)); 206 207 eb->indent_level++; 208 209 if (eb->wrapped_editor) 210 SVN_ERR(eb->wrapped_editor->add_file(path, 211 pb->wrapped_dir_baton, 212 copyfrom_path, 213 copyfrom_revision, 214 pool, 215 &fb->wrapped_file_baton)); 216 217 fb->edit_baton = eb; 218 *file_baton = fb; 219 220 return SVN_NO_ERROR; 221} 222 223static svn_error_t * 224open_file(const char *path, 225 void *parent_baton, 226 svn_revnum_t base_revision, 227 apr_pool_t *pool, 228 void **file_baton) 229{ 230 struct dir_baton *pb = parent_baton; 231 struct edit_baton *eb = pb->edit_baton; 232 struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); 233 234 SVN_ERR(write_indent(eb, pool)); 235 SVN_ERR(svn_stream_printf(eb->out, pool, "open_file : '%s':%ld\n", 236 path, base_revision)); 237 238 eb->indent_level++; 239 240 if (eb->wrapped_editor) 241 SVN_ERR(eb->wrapped_editor->open_file(path, 242 pb->wrapped_dir_baton, 243 base_revision, 244 pool, 245 &fb->wrapped_file_baton)); 246 247 fb->edit_baton = eb; 248 *file_baton = fb; 249 250 return SVN_NO_ERROR; 251} 252 253static svn_error_t * 254apply_textdelta(void *file_baton, 255 const char *base_checksum, 256 apr_pool_t *pool, 257 svn_txdelta_window_handler_t *handler, 258 void **handler_baton) 259{ 260 struct file_baton *fb = file_baton; 261 struct edit_baton *eb = fb->edit_baton; 262 263 SVN_ERR(write_indent(eb, pool)); 264 SVN_ERR(svn_stream_printf(eb->out, pool, "apply_textdelta : %s\n", 265 base_checksum)); 266 267 if (eb->wrapped_editor) 268 SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton, 269 base_checksum, 270 pool, 271 handler, 272 handler_baton)); 273 274 return SVN_NO_ERROR; 275} 276 277static svn_error_t * 278apply_textdelta_stream(const struct svn_delta_editor_t *editor, 279 void *file_baton, 280 const char *base_checksum, 281 svn_txdelta_stream_open_func_t open_func, 282 void *open_baton, 283 apr_pool_t *scratch_pool) 284{ 285 struct file_baton *fb = file_baton; 286 struct edit_baton *eb = fb->edit_baton; 287 288 SVN_ERR(write_indent(eb, scratch_pool)); 289 SVN_ERR(svn_stream_printf(eb->out, scratch_pool, 290 "apply_textdelta_stream : %s\n", 291 base_checksum)); 292 293 if (eb->wrapped_editor) 294 SVN_ERR(eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor, 295 fb->wrapped_file_baton, 296 base_checksum, 297 open_func, open_baton, 298 scratch_pool)); 299 300 return SVN_NO_ERROR; 301} 302 303static svn_error_t * 304close_file(void *file_baton, 305 const char *text_checksum, 306 apr_pool_t *pool) 307{ 308 struct file_baton *fb = file_baton; 309 struct edit_baton *eb = fb->edit_baton; 310 311 eb->indent_level--; 312 313 SVN_ERR(write_indent(eb, pool)); 314 SVN_ERR(svn_stream_printf(eb->out, pool, "close_file : %s\n", 315 text_checksum)); 316 317 if (eb->wrapped_editor) 318 SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton, 319 text_checksum, pool)); 320 321 return SVN_NO_ERROR; 322} 323 324static svn_error_t * 325absent_file(const char *path, 326 void *file_baton, 327 apr_pool_t *pool) 328{ 329 struct file_baton *fb = file_baton; 330 struct edit_baton *eb = fb->edit_baton; 331 332 SVN_ERR(write_indent(eb, pool)); 333 SVN_ERR(svn_stream_printf(eb->out, pool, "absent_file : %s\n", path)); 334 335 if (eb->wrapped_editor) 336 SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton, 337 pool)); 338 339 return SVN_NO_ERROR; 340} 341 342static svn_error_t * 343close_directory(void *dir_baton, 344 apr_pool_t *pool) 345{ 346 struct dir_baton *db = dir_baton; 347 struct edit_baton *eb = db->edit_baton; 348 349 eb->indent_level--; 350 SVN_ERR(write_indent(eb, pool)); 351 SVN_ERR(svn_stream_printf(eb->out, pool, "close_directory\n")); 352 353 if (eb->wrapped_editor) 354 SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton, 355 pool)); 356 357 return SVN_NO_ERROR; 358} 359 360static svn_error_t * 361absent_directory(const char *path, 362 void *dir_baton, 363 apr_pool_t *pool) 364{ 365 struct dir_baton *db = dir_baton; 366 struct edit_baton *eb = db->edit_baton; 367 368 SVN_ERR(write_indent(eb, pool)); 369 SVN_ERR(svn_stream_printf(eb->out, pool, "absent_directory : %s\n", 370 path)); 371 372 if (eb->wrapped_editor) 373 SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton, 374 pool)); 375 376 return SVN_NO_ERROR; 377} 378 379static svn_error_t * 380change_file_prop(void *file_baton, 381 const char *name, 382 const svn_string_t *value, 383 apr_pool_t *pool) 384{ 385 struct file_baton *fb = file_baton; 386 struct edit_baton *eb = fb->edit_baton; 387 388 SVN_ERR(write_indent(eb, pool)); 389 SVN_ERR(svn_stream_printf(eb->out, pool, "change_file_prop : %s -> %s\n", 390 name, value ? value->data : "<deleted>")); 391 392 if (eb->wrapped_editor) 393 SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton, 394 name, 395 value, 396 pool)); 397 398 return SVN_NO_ERROR; 399} 400 401static svn_error_t * 402change_dir_prop(void *dir_baton, 403 const char *name, 404 const svn_string_t *value, 405 apr_pool_t *pool) 406{ 407 struct dir_baton *db = dir_baton; 408 struct edit_baton *eb = db->edit_baton; 409 410 SVN_ERR(write_indent(eb, pool)); 411 SVN_ERR(svn_stream_printf(eb->out, pool, "change_dir_prop : %s -> %s\n", 412 name, value ? value->data : "<deleted>")); 413 414 if (eb->wrapped_editor) 415 SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton, 416 name, 417 value, 418 pool)); 419 420 return SVN_NO_ERROR; 421} 422 423static svn_error_t * 424close_edit(void *edit_baton, 425 apr_pool_t *pool) 426{ 427 struct edit_baton *eb = edit_baton; 428 429 SVN_ERR(write_indent(eb, pool)); 430 SVN_ERR(svn_stream_printf(eb->out, pool, "close_edit\n")); 431 432 if (eb->wrapped_editor) 433 SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool)); 434 435 return SVN_NO_ERROR; 436} 437 438static svn_error_t * 439abort_edit(void *edit_baton, 440 apr_pool_t *pool) 441{ 442 struct edit_baton *eb = edit_baton; 443 444 SVN_ERR(write_indent(eb, pool)); 445 SVN_ERR(svn_stream_printf(eb->out, pool, "abort_edit\n")); 446 447 if (eb->wrapped_editor) 448 SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool)); 449 450 return SVN_NO_ERROR; 451} 452 453svn_error_t * 454svn_delta__get_debug_editor(const svn_delta_editor_t **editor, 455 void **edit_baton, 456 const svn_delta_editor_t *wrapped_editor, 457 void *wrapped_edit_baton, 458 const char *prefix, 459 apr_pool_t *pool) 460{ 461 svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool); 462 struct edit_baton *eb = apr_palloc(pool, sizeof(*eb)); 463 apr_file_t *errfp; 464 svn_stream_t *out; 465 466 apr_status_t apr_err = apr_file_open_stdout(&errfp, pool); 467 if (apr_err) 468 return svn_error_wrap_apr(apr_err, "Problem opening stderr"); 469 470 out = svn_stream_from_aprfile2(errfp, TRUE, pool); 471 472 tree_editor->set_target_revision = set_target_revision; 473 tree_editor->open_root = open_root; 474 tree_editor->delete_entry = delete_entry; 475 tree_editor->add_directory = add_directory; 476 tree_editor->open_directory = open_directory; 477 tree_editor->change_dir_prop = change_dir_prop; 478 tree_editor->close_directory = close_directory; 479 tree_editor->absent_directory = absent_directory; 480 tree_editor->add_file = add_file; 481 tree_editor->open_file = open_file; 482 tree_editor->apply_textdelta = apply_textdelta; 483 tree_editor->apply_textdelta_stream = apply_textdelta_stream; 484 tree_editor->change_file_prop = change_file_prop; 485 tree_editor->close_file = close_file; 486 tree_editor->absent_file = absent_file; 487 tree_editor->close_edit = close_edit; 488 tree_editor->abort_edit = abort_edit; 489 490 eb->wrapped_editor = wrapped_editor; 491 eb->wrapped_edit_baton = wrapped_edit_baton; 492 eb->out = out; 493 eb->indent_level = 0; 494 /* This is DBG_FLAG from ../libsvn_subr/debug.c */ 495 eb->prefix = apr_pstrcat(pool, "DBG: ", prefix, SVN_VA_NULL); 496 497 *editor = tree_editor; 498 *edit_baton = eb; 499 500 return SVN_NO_ERROR; 501} 502