1251881Speter/* 2251881Speter * diff_tree.c : default diff tree processor 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter#include <apr.h> 25251881Speter#include <apr_pools.h> 26251881Speter#include <apr_general.h> 27251881Speter 28251881Speter#include <assert.h> 29251881Speter 30251881Speter#include "svn_dirent_uri.h" 31251881Speter#include "svn_error.h" 32251881Speter#include "svn_io.h" 33251881Speter#include "svn_pools.h" 34251881Speter#include "svn_props.h" 35251881Speter#include "svn_types.h" 36251881Speter 37251881Speter#include "private/svn_diff_tree.h" 38251881Speter#include "svn_private_config.h" 39251881Speter 40251881Spetertypedef struct tree_processor_t 41251881Speter{ 42251881Speter svn_diff_tree_processor_t tp; 43251881Speter 44251881Speter /* void *future_extension */ 45251881Speter} tree_processor_t; 46251881Speter 47251881Speter 48251881Speterstatic svn_error_t * 49251881Speterdefault_dir_opened(void **new_dir_baton, 50251881Speter svn_boolean_t *skip, 51251881Speter svn_boolean_t *skip_children, 52251881Speter const char *relpath, 53251881Speter const svn_diff_source_t *left_source, 54251881Speter const svn_diff_source_t *right_source, 55251881Speter const svn_diff_source_t *copyfrom_source, 56251881Speter void *parent_dir_baton, 57251881Speter const svn_diff_tree_processor_t *processor, 58251881Speter apr_pool_t *result_pool, 59251881Speter apr_pool_t *scratch_pool) 60251881Speter{ 61251881Speter *new_dir_baton = NULL; 62251881Speter return SVN_NO_ERROR; 63251881Speter} 64251881Speter 65251881Speterstatic svn_error_t * 66251881Speterdefault_dir_added(const char *relpath, 67251881Speter const svn_diff_source_t *copyfrom_source, 68251881Speter const svn_diff_source_t *right_source, 69251881Speter /*const*/ apr_hash_t *copyfrom_props, 70251881Speter /*const*/ apr_hash_t *right_props, 71251881Speter void *dir_baton, 72251881Speter const svn_diff_tree_processor_t *processor, 73251881Speter apr_pool_t *scratch_pool) 74251881Speter{ 75251881Speter SVN_ERR(processor->dir_closed(relpath, NULL, right_source, 76251881Speter dir_baton, processor, 77251881Speter scratch_pool)); 78251881Speter 79251881Speter return SVN_NO_ERROR; 80251881Speter} 81251881Speter 82251881Speterstatic svn_error_t * 83251881Speterdefault_dir_deleted(const char *relpath, 84251881Speter const svn_diff_source_t *left_source, 85251881Speter /*const*/ apr_hash_t *left_props, 86251881Speter void *dir_baton, 87251881Speter const svn_diff_tree_processor_t *processor, 88251881Speter apr_pool_t *scratch_pool) 89251881Speter{ 90251881Speter SVN_ERR(processor->dir_closed(relpath, left_source, NULL, 91251881Speter dir_baton, processor, 92251881Speter scratch_pool)); 93251881Speter return SVN_NO_ERROR; 94251881Speter} 95251881Speter 96251881Speterstatic svn_error_t * 97251881Speterdefault_dir_changed(const char *relpath, 98251881Speter const svn_diff_source_t *left_source, 99251881Speter const svn_diff_source_t *right_source, 100251881Speter /*const*/ apr_hash_t *left_props, 101251881Speter /*const*/ apr_hash_t *right_props, 102251881Speter const apr_array_header_t *prop_changes, 103251881Speter void *dir_baton, 104251881Speter const struct svn_diff_tree_processor_t *processor, 105251881Speter apr_pool_t *scratch_pool) 106251881Speter{ 107251881Speter SVN_ERR(processor->dir_closed(relpath, 108251881Speter left_source, right_source, 109251881Speter dir_baton, 110251881Speter processor, scratch_pool)); 111251881Speter return SVN_NO_ERROR; 112251881Speter} 113251881Speter 114251881Speterstatic svn_error_t * 115251881Speterdefault_dir_closed(const char *relpath, 116251881Speter const svn_diff_source_t *left_source, 117251881Speter const svn_diff_source_t *right_source, 118251881Speter void *dir_baton, 119251881Speter const svn_diff_tree_processor_t *processor, 120251881Speter apr_pool_t *scratch_pool) 121251881Speter{ 122251881Speter return SVN_NO_ERROR; 123251881Speter} 124251881Speter 125251881Speterstatic svn_error_t * 126251881Speterdefault_file_opened(void **new_file_baton, 127251881Speter svn_boolean_t *skip, 128251881Speter const char *relpath, 129251881Speter const svn_diff_source_t *left_source, 130251881Speter const svn_diff_source_t *right_source, 131251881Speter const svn_diff_source_t *copyfrom_source, 132251881Speter void *dir_baton, 133251881Speter const svn_diff_tree_processor_t *processor, 134251881Speter apr_pool_t *result_pool, 135251881Speter apr_pool_t *scratch_pool) 136251881Speter{ 137251881Speter *new_file_baton = dir_baton; 138251881Speter return SVN_NO_ERROR; 139251881Speter} 140251881Speter 141251881Speterstatic svn_error_t * 142251881Speterdefault_file_added(const char *relpath, 143251881Speter const svn_diff_source_t *copyfrom_source, 144251881Speter const svn_diff_source_t *right_source, 145251881Speter const char *copyfrom_file, 146251881Speter const char *right_file, 147251881Speter /*const*/ apr_hash_t *copyfrom_props, 148251881Speter /*const*/ apr_hash_t *right_props, 149251881Speter void *file_baton, 150251881Speter const svn_diff_tree_processor_t *processor, 151251881Speter apr_pool_t *scratch_pool) 152251881Speter{ 153251881Speter SVN_ERR(processor->file_closed(relpath, 154251881Speter NULL, right_source, 155251881Speter file_baton, processor, scratch_pool)); 156251881Speter return SVN_NO_ERROR; 157251881Speter} 158251881Speter 159251881Speterstatic svn_error_t * 160251881Speterdefault_file_deleted(const char *relpath, 161251881Speter const svn_diff_source_t *left_source, 162251881Speter const char *left_file, 163251881Speter /*const*/ apr_hash_t *left_props, 164251881Speter void *file_baton, 165251881Speter const svn_diff_tree_processor_t *processor, 166251881Speter apr_pool_t *scratch_pool) 167251881Speter{ 168251881Speter SVN_ERR(processor->file_closed(relpath, 169251881Speter left_source, NULL, 170251881Speter file_baton, processor, scratch_pool)); 171251881Speter return SVN_NO_ERROR; 172251881Speter} 173251881Speter 174251881Speterstatic svn_error_t * 175251881Speterdefault_file_changed(const char *relpath, 176251881Speter const svn_diff_source_t *left_source, 177251881Speter const svn_diff_source_t *right_source, 178251881Speter const char *left_file, 179251881Speter const char *right_file, 180251881Speter /*const*/ apr_hash_t *left_props, 181251881Speter /*const*/ apr_hash_t *right_props, 182251881Speter svn_boolean_t file_modified, 183251881Speter const apr_array_header_t *prop_changes, 184251881Speter void *file_baton, 185251881Speter const svn_diff_tree_processor_t *processor, 186251881Speter apr_pool_t *scratch_pool) 187251881Speter{ 188251881Speter SVN_ERR(processor->file_closed(relpath, 189251881Speter left_source, right_source, 190251881Speter file_baton, processor, scratch_pool)); 191251881Speter return SVN_NO_ERROR; 192251881Speter} 193251881Speter 194251881Speterstatic svn_error_t * 195251881Speterdefault_file_closed(const char *relpath, 196251881Speter const svn_diff_source_t *left_source, 197251881Speter const svn_diff_source_t *right_source, 198251881Speter void *file_baton, 199251881Speter const svn_diff_tree_processor_t *processor, 200251881Speter apr_pool_t *scratch_pool) 201251881Speter{ 202251881Speter return SVN_NO_ERROR; 203251881Speter} 204251881Speter 205251881Speterstatic svn_error_t * 206251881Speterdefault_node_absent(const char *relpath, 207251881Speter void *dir_baton, 208251881Speter const svn_diff_tree_processor_t *processor, 209251881Speter apr_pool_t *scratch_pool) 210251881Speter{ 211251881Speter return SVN_NO_ERROR; 212251881Speter} 213251881Speter 214251881Spetersvn_diff_tree_processor_t * 215251881Spetersvn_diff__tree_processor_create(void *baton, 216251881Speter apr_pool_t *result_pool) 217251881Speter{ 218251881Speter tree_processor_t *wrapper; 219251881Speter wrapper = apr_pcalloc(result_pool, sizeof(*wrapper)); 220251881Speter 221251881Speter wrapper->tp.baton = baton; 222251881Speter 223251881Speter wrapper->tp.dir_opened = default_dir_opened; 224251881Speter wrapper->tp.dir_added = default_dir_added; 225251881Speter wrapper->tp.dir_deleted = default_dir_deleted; 226251881Speter wrapper->tp.dir_changed = default_dir_changed; 227251881Speter wrapper->tp.dir_closed = default_dir_closed; 228251881Speter 229251881Speter wrapper->tp.file_opened = default_file_opened; 230251881Speter wrapper->tp.file_added = default_file_added; 231251881Speter wrapper->tp.file_deleted = default_file_deleted; 232251881Speter wrapper->tp.file_changed = default_file_changed; 233251881Speter wrapper->tp.file_closed = default_file_closed; 234251881Speter 235251881Speter wrapper->tp.node_absent = default_node_absent; 236251881Speter 237251881Speter 238251881Speter return &wrapper->tp; 239251881Speter} 240251881Speter 241251881Speterstruct reverse_tree_baton_t 242251881Speter{ 243251881Speter const svn_diff_tree_processor_t *processor; 244251881Speter const char *prefix_relpath; 245251881Speter}; 246251881Speter 247251881Speterstatic svn_error_t * 248251881Speterreverse_dir_opened(void **new_dir_baton, 249251881Speter svn_boolean_t *skip, 250251881Speter svn_boolean_t *skip_children, 251251881Speter const char *relpath, 252251881Speter const svn_diff_source_t *left_source, 253251881Speter const svn_diff_source_t *right_source, 254251881Speter const svn_diff_source_t *copyfrom_source, 255251881Speter void *parent_dir_baton, 256251881Speter const svn_diff_tree_processor_t *processor, 257251881Speter apr_pool_t *result_pool, 258251881Speter apr_pool_t *scratch_pool) 259251881Speter{ 260251881Speter struct reverse_tree_baton_t *rb = processor->baton; 261251881Speter 262251881Speter if (rb->prefix_relpath) 263251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 264251881Speter 265251881Speter SVN_ERR(rb->processor->dir_opened(new_dir_baton, skip, skip_children, 266251881Speter relpath, 267251881Speter right_source, left_source, 268251881Speter NULL /* copyfrom */, 269251881Speter parent_dir_baton, 270251881Speter rb->processor, 271251881Speter result_pool, scratch_pool)); 272251881Speter return SVN_NO_ERROR; 273251881Speter} 274251881Speter 275251881Speterstatic svn_error_t * 276251881Speterreverse_dir_added(const char *relpath, 277251881Speter const svn_diff_source_t *copyfrom_source, 278251881Speter const svn_diff_source_t *right_source, 279251881Speter /*const*/ apr_hash_t *copyfrom_props, 280251881Speter /*const*/ apr_hash_t *right_props, 281251881Speter void *dir_baton, 282251881Speter const svn_diff_tree_processor_t *processor, 283251881Speter apr_pool_t *scratch_pool) 284251881Speter{ 285251881Speter struct reverse_tree_baton_t *rb = processor->baton; 286251881Speter 287251881Speter if (rb->prefix_relpath) 288251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 289251881Speter 290251881Speter SVN_ERR(rb->processor->dir_deleted(relpath, 291251881Speter right_source, 292251881Speter right_props, 293251881Speter dir_baton, 294251881Speter rb->processor, 295251881Speter scratch_pool)); 296251881Speter 297251881Speter return SVN_NO_ERROR; 298251881Speter} 299251881Speter 300251881Speterstatic svn_error_t * 301251881Speterreverse_dir_deleted(const char *relpath, 302251881Speter const svn_diff_source_t *left_source, 303251881Speter /*const*/ apr_hash_t *left_props, 304251881Speter void *dir_baton, 305251881Speter const svn_diff_tree_processor_t *processor, 306251881Speter apr_pool_t *scratch_pool) 307251881Speter{ 308251881Speter struct reverse_tree_baton_t *rb = processor->baton; 309251881Speter 310251881Speter if (rb->prefix_relpath) 311251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 312251881Speter 313251881Speter SVN_ERR(rb->processor->dir_added(relpath, 314251881Speter NULL, 315251881Speter left_source, 316251881Speter NULL, 317251881Speter left_props, 318251881Speter dir_baton, 319251881Speter rb->processor, 320251881Speter scratch_pool)); 321251881Speter return SVN_NO_ERROR; 322251881Speter} 323251881Speter 324251881Speterstatic svn_error_t * 325251881Speterreverse_dir_changed(const char *relpath, 326251881Speter const svn_diff_source_t *left_source, 327251881Speter const svn_diff_source_t *right_source, 328251881Speter /*const*/ apr_hash_t *left_props, 329251881Speter /*const*/ apr_hash_t *right_props, 330251881Speter const apr_array_header_t *prop_changes, 331251881Speter void *dir_baton, 332251881Speter const struct svn_diff_tree_processor_t *processor, 333251881Speter apr_pool_t *scratch_pool) 334251881Speter{ 335251881Speter struct reverse_tree_baton_t *rb = processor->baton; 336251881Speter apr_array_header_t *reversed_prop_changes = NULL; 337251881Speter 338251881Speter if (rb->prefix_relpath) 339251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 340251881Speter 341251881Speter if (prop_changes) 342251881Speter { 343251881Speter SVN_ERR_ASSERT(left_props != NULL && right_props != NULL); 344251881Speter SVN_ERR(svn_prop_diffs(&reversed_prop_changes, left_props, right_props, 345251881Speter scratch_pool)); 346251881Speter } 347251881Speter 348251881Speter SVN_ERR(rb->processor->dir_changed(relpath, 349251881Speter right_source, 350251881Speter left_source, 351251881Speter right_props, 352251881Speter left_props, 353251881Speter reversed_prop_changes, 354251881Speter dir_baton, 355251881Speter rb->processor, 356251881Speter scratch_pool)); 357251881Speter return SVN_NO_ERROR; 358251881Speter} 359251881Speter 360251881Speterstatic svn_error_t * 361251881Speterreverse_dir_closed(const char *relpath, 362251881Speter const svn_diff_source_t *left_source, 363251881Speter const svn_diff_source_t *right_source, 364251881Speter void *dir_baton, 365251881Speter const svn_diff_tree_processor_t *processor, 366251881Speter apr_pool_t *scratch_pool) 367251881Speter{ 368251881Speter struct reverse_tree_baton_t *rb = processor->baton; 369251881Speter 370251881Speter if (rb->prefix_relpath) 371251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 372251881Speter 373251881Speter SVN_ERR(rb->processor->dir_closed(relpath, 374251881Speter right_source, 375251881Speter left_source, 376251881Speter dir_baton, 377251881Speter rb->processor, 378251881Speter scratch_pool)); 379251881Speter return SVN_NO_ERROR; 380251881Speter} 381251881Speter 382251881Speterstatic svn_error_t * 383251881Speterreverse_file_opened(void **new_file_baton, 384251881Speter svn_boolean_t *skip, 385251881Speter const char *relpath, 386251881Speter const svn_diff_source_t *left_source, 387251881Speter const svn_diff_source_t *right_source, 388251881Speter const svn_diff_source_t *copyfrom_source, 389251881Speter void *dir_baton, 390251881Speter const svn_diff_tree_processor_t *processor, 391251881Speter apr_pool_t *result_pool, 392251881Speter apr_pool_t *scratch_pool) 393251881Speter{ 394251881Speter struct reverse_tree_baton_t *rb = processor->baton; 395251881Speter 396251881Speter if (rb->prefix_relpath) 397251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 398251881Speter 399251881Speter SVN_ERR(rb->processor->file_opened(new_file_baton, 400251881Speter skip, 401251881Speter relpath, 402251881Speter right_source, 403251881Speter left_source, 404251881Speter NULL /* copy_from */, 405251881Speter dir_baton, 406251881Speter rb->processor, 407251881Speter result_pool, 408251881Speter scratch_pool)); 409251881Speter return SVN_NO_ERROR; 410251881Speter} 411251881Speter 412251881Speterstatic svn_error_t * 413251881Speterreverse_file_added(const char *relpath, 414251881Speter const svn_diff_source_t *copyfrom_source, 415251881Speter const svn_diff_source_t *right_source, 416251881Speter const char *copyfrom_file, 417251881Speter const char *right_file, 418251881Speter /*const*/ apr_hash_t *copyfrom_props, 419251881Speter /*const*/ apr_hash_t *right_props, 420251881Speter void *file_baton, 421251881Speter const svn_diff_tree_processor_t *processor, 422251881Speter apr_pool_t *scratch_pool) 423251881Speter{ 424251881Speter struct reverse_tree_baton_t *rb = processor->baton; 425251881Speter 426251881Speter if (rb->prefix_relpath) 427251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 428251881Speter 429251881Speter SVN_ERR(rb->processor->file_deleted(relpath, 430251881Speter right_source, 431251881Speter right_file, 432251881Speter right_props, 433251881Speter file_baton, 434251881Speter rb->processor, 435251881Speter scratch_pool)); 436251881Speter return SVN_NO_ERROR; 437251881Speter} 438251881Speter 439251881Speterstatic svn_error_t * 440251881Speterreverse_file_deleted(const char *relpath, 441251881Speter const svn_diff_source_t *left_source, 442251881Speter const char *left_file, 443251881Speter /*const*/ apr_hash_t *left_props, 444251881Speter void *file_baton, 445251881Speter const svn_diff_tree_processor_t *processor, 446251881Speter apr_pool_t *scratch_pool) 447251881Speter{ 448251881Speter struct reverse_tree_baton_t *rb = processor->baton; 449251881Speter 450251881Speter if (rb->prefix_relpath) 451251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 452251881Speter 453251881Speter SVN_ERR(rb->processor->file_added(relpath, 454251881Speter NULL /* copyfrom src */, 455251881Speter left_source, 456251881Speter NULL /* copyfrom file */, 457251881Speter left_file, 458251881Speter NULL /* copyfrom props */, 459251881Speter left_props, 460251881Speter file_baton, 461251881Speter rb->processor, 462251881Speter scratch_pool)); 463251881Speter return SVN_NO_ERROR; 464251881Speter} 465251881Speter 466251881Speterstatic svn_error_t * 467251881Speterreverse_file_changed(const char *relpath, 468251881Speter const svn_diff_source_t *left_source, 469251881Speter const svn_diff_source_t *right_source, 470251881Speter const char *left_file, 471251881Speter const char *right_file, 472251881Speter /*const*/ apr_hash_t *left_props, 473251881Speter /*const*/ apr_hash_t *right_props, 474251881Speter svn_boolean_t file_modified, 475251881Speter const apr_array_header_t *prop_changes, 476251881Speter void *file_baton, 477251881Speter const svn_diff_tree_processor_t *processor, 478251881Speter apr_pool_t *scratch_pool) 479251881Speter{ 480251881Speter struct reverse_tree_baton_t *rb = processor->baton; 481251881Speter apr_array_header_t *reversed_prop_changes = NULL; 482251881Speter 483251881Speter if (rb->prefix_relpath) 484251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 485251881Speter 486251881Speter if (prop_changes) 487251881Speter { 488251881Speter SVN_ERR_ASSERT(left_props != NULL && right_props != NULL); 489251881Speter SVN_ERR(svn_prop_diffs(&reversed_prop_changes, left_props, right_props, 490251881Speter scratch_pool)); 491251881Speter } 492251881Speter 493251881Speter SVN_ERR(rb->processor->file_changed(relpath, 494251881Speter right_source, 495251881Speter left_source, 496251881Speter right_file, 497251881Speter left_file, 498251881Speter right_props, 499251881Speter left_props, 500251881Speter file_modified, 501251881Speter reversed_prop_changes, 502251881Speter file_baton, 503251881Speter rb->processor, 504251881Speter scratch_pool)); 505251881Speter return SVN_NO_ERROR; 506251881Speter} 507251881Speter 508251881Speterstatic svn_error_t * 509251881Speterreverse_file_closed(const char *relpath, 510251881Speter const svn_diff_source_t *left_source, 511251881Speter const svn_diff_source_t *right_source, 512251881Speter void *file_baton, 513251881Speter const svn_diff_tree_processor_t *processor, 514251881Speter apr_pool_t *scratch_pool) 515251881Speter{ 516251881Speter struct reverse_tree_baton_t *rb = processor->baton; 517251881Speter 518251881Speter if (rb->prefix_relpath) 519251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 520251881Speter 521251881Speter SVN_ERR(rb->processor->file_closed(relpath, 522251881Speter right_source, 523251881Speter left_source, 524251881Speter file_baton, 525251881Speter rb->processor, 526251881Speter scratch_pool)); 527251881Speter 528251881Speter return SVN_NO_ERROR; 529251881Speter} 530251881Speter 531251881Speterstatic svn_error_t * 532251881Speterreverse_node_absent(const char *relpath, 533251881Speter void *dir_baton, 534251881Speter const svn_diff_tree_processor_t *processor, 535251881Speter apr_pool_t *scratch_pool) 536251881Speter{ 537251881Speter struct reverse_tree_baton_t *rb = processor->baton; 538251881Speter 539251881Speter if (rb->prefix_relpath) 540251881Speter relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool); 541251881Speter 542251881Speter SVN_ERR(rb->processor->node_absent(relpath, 543251881Speter dir_baton, 544251881Speter rb->processor, 545251881Speter scratch_pool)); 546251881Speter return SVN_NO_ERROR; 547251881Speter} 548251881Speter 549251881Speter 550251881Speterconst svn_diff_tree_processor_t * 551251881Spetersvn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor, 552251881Speter const char *prefix_relpath, 553251881Speter apr_pool_t *result_pool) 554251881Speter{ 555251881Speter struct reverse_tree_baton_t *rb; 556251881Speter svn_diff_tree_processor_t *reverse; 557251881Speter 558251881Speter rb = apr_pcalloc(result_pool, sizeof(*rb)); 559251881Speter rb->processor = processor; 560251881Speter if (prefix_relpath) 561251881Speter rb->prefix_relpath = apr_pstrdup(result_pool, prefix_relpath); 562251881Speter 563251881Speter reverse = svn_diff__tree_processor_create(rb, result_pool); 564251881Speter 565251881Speter reverse->dir_opened = reverse_dir_opened; 566251881Speter reverse->dir_added = reverse_dir_added; 567251881Speter reverse->dir_deleted = reverse_dir_deleted; 568251881Speter reverse->dir_changed = reverse_dir_changed; 569251881Speter reverse->dir_closed = reverse_dir_closed; 570251881Speter 571251881Speter reverse->file_opened = reverse_file_opened; 572251881Speter reverse->file_added = reverse_file_added; 573251881Speter reverse->file_deleted = reverse_file_deleted; 574251881Speter reverse->file_changed = reverse_file_changed; 575251881Speter reverse->file_closed = reverse_file_closed; 576251881Speter 577251881Speter reverse->node_absent = reverse_node_absent; 578251881Speter 579251881Speter return reverse; 580251881Speter} 581251881Speter 582251881Speterstruct filter_tree_baton_t 583251881Speter{ 584251881Speter const svn_diff_tree_processor_t *processor; 585251881Speter const char *prefix_relpath; 586251881Speter}; 587251881Speter 588251881Speterstatic svn_error_t * 589251881Speterfilter_dir_opened(void **new_dir_baton, 590251881Speter svn_boolean_t *skip, 591251881Speter svn_boolean_t *skip_children, 592251881Speter const char *relpath, 593251881Speter const svn_diff_source_t *left_source, 594251881Speter const svn_diff_source_t *right_source, 595251881Speter const svn_diff_source_t *copyfrom_source, 596251881Speter void *parent_dir_baton, 597251881Speter const svn_diff_tree_processor_t *processor, 598251881Speter apr_pool_t *result_pool, 599251881Speter apr_pool_t *scratch_pool) 600251881Speter{ 601251881Speter struct filter_tree_baton_t *fb = processor->baton; 602251881Speter 603251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 604251881Speter 605251881Speter if (! relpath) 606251881Speter { 607251881Speter /* Skip work for this, but NOT for DESCENDANTS */ 608251881Speter *skip = TRUE; 609251881Speter return SVN_NO_ERROR; 610251881Speter } 611251881Speter 612251881Speter SVN_ERR(fb->processor->dir_opened(new_dir_baton, skip, skip_children, 613251881Speter relpath, 614251881Speter left_source, right_source, 615251881Speter copyfrom_source, 616251881Speter parent_dir_baton, 617251881Speter fb->processor, 618251881Speter result_pool, scratch_pool)); 619251881Speter return SVN_NO_ERROR; 620251881Speter} 621251881Speter 622251881Speterstatic svn_error_t * 623251881Speterfilter_dir_added(const char *relpath, 624251881Speter const svn_diff_source_t *copyfrom_source, 625251881Speter const svn_diff_source_t *right_source, 626251881Speter /*const*/ apr_hash_t *copyfrom_props, 627251881Speter /*const*/ apr_hash_t *right_props, 628251881Speter void *dir_baton, 629251881Speter const svn_diff_tree_processor_t *processor, 630251881Speter apr_pool_t *scratch_pool) 631251881Speter{ 632251881Speter struct filter_tree_baton_t *fb = processor->baton; 633251881Speter 634251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 635251881Speter assert(relpath != NULL); /* Driver error */ 636251881Speter 637251881Speter SVN_ERR(fb->processor->dir_added(relpath, 638251881Speter copyfrom_source, 639251881Speter right_source, 640251881Speter copyfrom_props, 641251881Speter right_props, 642251881Speter dir_baton, 643251881Speter fb->processor, 644251881Speter scratch_pool)); 645251881Speter 646251881Speter return SVN_NO_ERROR; 647251881Speter} 648251881Speter 649251881Speterstatic svn_error_t * 650251881Speterfilter_dir_deleted(const char *relpath, 651251881Speter const svn_diff_source_t *left_source, 652251881Speter /*const*/ apr_hash_t *left_props, 653251881Speter void *dir_baton, 654251881Speter const svn_diff_tree_processor_t *processor, 655251881Speter apr_pool_t *scratch_pool) 656251881Speter{ 657251881Speter struct filter_tree_baton_t *fb = processor->baton; 658251881Speter 659251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 660251881Speter assert(relpath != NULL); /* Driver error */ 661251881Speter 662251881Speter SVN_ERR(fb->processor->dir_deleted(relpath, 663251881Speter left_source, 664251881Speter left_props, 665251881Speter dir_baton, 666251881Speter fb->processor, 667251881Speter scratch_pool)); 668251881Speter 669251881Speter return SVN_NO_ERROR; 670251881Speter} 671251881Speter 672251881Speterstatic svn_error_t * 673251881Speterfilter_dir_changed(const char *relpath, 674251881Speter const svn_diff_source_t *left_source, 675251881Speter const svn_diff_source_t *right_source, 676251881Speter /*const*/ apr_hash_t *left_props, 677251881Speter /*const*/ apr_hash_t *right_props, 678251881Speter const apr_array_header_t *prop_changes, 679251881Speter void *dir_baton, 680251881Speter const struct svn_diff_tree_processor_t *processor, 681251881Speter apr_pool_t *scratch_pool) 682251881Speter{ 683251881Speter struct filter_tree_baton_t *fb = processor->baton; 684251881Speter 685251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 686251881Speter assert(relpath != NULL); /* Driver error */ 687251881Speter 688251881Speter SVN_ERR(fb->processor->dir_changed(relpath, 689251881Speter left_source, 690251881Speter right_source, 691251881Speter left_props, 692251881Speter right_props, 693251881Speter prop_changes, 694251881Speter dir_baton, 695251881Speter fb->processor, 696251881Speter scratch_pool)); 697251881Speter return SVN_NO_ERROR; 698251881Speter} 699251881Speter 700251881Speterstatic svn_error_t * 701251881Speterfilter_dir_closed(const char *relpath, 702251881Speter const svn_diff_source_t *left_source, 703251881Speter const svn_diff_source_t *right_source, 704251881Speter void *dir_baton, 705251881Speter const svn_diff_tree_processor_t *processor, 706251881Speter apr_pool_t *scratch_pool) 707251881Speter{ 708251881Speter struct filter_tree_baton_t *fb = processor->baton; 709251881Speter 710251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 711251881Speter assert(relpath != NULL); /* Driver error */ 712251881Speter 713251881Speter SVN_ERR(fb->processor->dir_closed(relpath, 714251881Speter left_source, 715251881Speter right_source, 716251881Speter dir_baton, 717251881Speter fb->processor, 718251881Speter scratch_pool)); 719251881Speter return SVN_NO_ERROR; 720251881Speter} 721251881Speter 722251881Speterstatic svn_error_t * 723251881Speterfilter_file_opened(void **new_file_baton, 724251881Speter svn_boolean_t *skip, 725251881Speter const char *relpath, 726251881Speter const svn_diff_source_t *left_source, 727251881Speter const svn_diff_source_t *right_source, 728251881Speter const svn_diff_source_t *copyfrom_source, 729251881Speter void *dir_baton, 730251881Speter const svn_diff_tree_processor_t *processor, 731251881Speter apr_pool_t *result_pool, 732251881Speter apr_pool_t *scratch_pool) 733251881Speter{ 734251881Speter struct filter_tree_baton_t *fb = processor->baton; 735251881Speter 736251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 737251881Speter 738251881Speter if (! relpath) 739251881Speter { 740251881Speter *skip = TRUE; 741251881Speter return SVN_NO_ERROR; 742251881Speter } 743251881Speter 744251881Speter SVN_ERR(fb->processor->file_opened(new_file_baton, 745251881Speter skip, 746251881Speter relpath, 747251881Speter left_source, 748251881Speter right_source, 749251881Speter copyfrom_source, 750251881Speter dir_baton, 751251881Speter fb->processor, 752251881Speter result_pool, 753251881Speter scratch_pool)); 754251881Speter return SVN_NO_ERROR; 755251881Speter} 756251881Speter 757251881Speterstatic svn_error_t * 758251881Speterfilter_file_added(const char *relpath, 759251881Speter const svn_diff_source_t *copyfrom_source, 760251881Speter const svn_diff_source_t *right_source, 761251881Speter const char *copyfrom_file, 762251881Speter const char *right_file, 763251881Speter /*const*/ apr_hash_t *copyfrom_props, 764251881Speter /*const*/ apr_hash_t *right_props, 765251881Speter void *file_baton, 766251881Speter const svn_diff_tree_processor_t *processor, 767251881Speter apr_pool_t *scratch_pool) 768251881Speter{ 769251881Speter struct filter_tree_baton_t *fb = processor->baton; 770251881Speter 771251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 772251881Speter assert(relpath != NULL); /* Driver error */ 773251881Speter 774251881Speter SVN_ERR(fb->processor->file_added(relpath, 775251881Speter copyfrom_source, 776251881Speter right_source, 777251881Speter copyfrom_file, 778251881Speter right_file, 779251881Speter copyfrom_props, 780251881Speter right_props, 781251881Speter file_baton, 782251881Speter fb->processor, 783251881Speter scratch_pool)); 784251881Speter return SVN_NO_ERROR; 785251881Speter} 786251881Speter 787251881Speterstatic svn_error_t * 788251881Speterfilter_file_deleted(const char *relpath, 789251881Speter const svn_diff_source_t *left_source, 790251881Speter const char *left_file, 791251881Speter /*const*/ apr_hash_t *left_props, 792251881Speter void *file_baton, 793251881Speter const svn_diff_tree_processor_t *processor, 794251881Speter apr_pool_t *scratch_pool) 795251881Speter{ 796251881Speter struct filter_tree_baton_t *fb = processor->baton; 797251881Speter 798251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 799251881Speter assert(relpath != NULL); /* Driver error */ 800251881Speter 801251881Speter SVN_ERR(fb->processor->file_deleted(relpath, 802251881Speter left_source, 803251881Speter left_file, 804251881Speter left_props, 805251881Speter file_baton, 806251881Speter fb->processor, 807251881Speter scratch_pool)); 808251881Speter 809251881Speter return SVN_NO_ERROR; 810251881Speter} 811251881Speter 812251881Speterstatic svn_error_t * 813251881Speterfilter_file_changed(const char *relpath, 814251881Speter const svn_diff_source_t *left_source, 815251881Speter const svn_diff_source_t *right_source, 816251881Speter const char *left_file, 817251881Speter const char *right_file, 818251881Speter /*const*/ apr_hash_t *left_props, 819251881Speter /*const*/ apr_hash_t *right_props, 820251881Speter svn_boolean_t file_modified, 821251881Speter const apr_array_header_t *prop_changes, 822251881Speter void *file_baton, 823251881Speter const svn_diff_tree_processor_t *processor, 824251881Speter apr_pool_t *scratch_pool) 825251881Speter{ 826251881Speter struct filter_tree_baton_t *fb = processor->baton; 827251881Speter 828251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 829251881Speter assert(relpath != NULL); /* Driver error */ 830251881Speter 831251881Speter SVN_ERR(fb->processor->file_changed(relpath, 832251881Speter left_source, 833251881Speter right_source, 834251881Speter left_file, 835251881Speter right_file, 836251881Speter left_props, 837251881Speter right_props, 838251881Speter file_modified, 839251881Speter prop_changes, 840251881Speter file_baton, 841251881Speter fb->processor, 842251881Speter scratch_pool)); 843251881Speter return SVN_NO_ERROR; 844251881Speter} 845251881Speter 846251881Speterstatic svn_error_t * 847251881Speterfilter_file_closed(const char *relpath, 848251881Speter const svn_diff_source_t *left_source, 849251881Speter const svn_diff_source_t *right_source, 850251881Speter void *file_baton, 851251881Speter const svn_diff_tree_processor_t *processor, 852251881Speter apr_pool_t *scratch_pool) 853251881Speter{ 854251881Speter struct filter_tree_baton_t *fb = processor->baton; 855251881Speter 856251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 857251881Speter assert(relpath != NULL); /* Driver error */ 858251881Speter 859251881Speter SVN_ERR(fb->processor->file_closed(relpath, 860251881Speter left_source, 861251881Speter right_source, 862251881Speter file_baton, 863251881Speter fb->processor, 864251881Speter scratch_pool)); 865251881Speter 866251881Speter return SVN_NO_ERROR; 867251881Speter} 868251881Speter 869251881Speterstatic svn_error_t * 870251881Speterfilter_node_absent(const char *relpath, 871251881Speter void *dir_baton, 872251881Speter const svn_diff_tree_processor_t *processor, 873251881Speter apr_pool_t *scratch_pool) 874251881Speter{ 875251881Speter struct filter_tree_baton_t *fb = processor->baton; 876251881Speter 877251881Speter relpath = svn_relpath_skip_ancestor(fb->prefix_relpath, relpath); 878251881Speter assert(relpath != NULL); /* Driver error */ 879251881Speter 880251881Speter SVN_ERR(fb->processor->node_absent(relpath, 881251881Speter dir_baton, 882251881Speter fb->processor, 883251881Speter scratch_pool)); 884251881Speter return SVN_NO_ERROR; 885251881Speter} 886251881Speter 887251881Speter 888251881Speterconst svn_diff_tree_processor_t * 889251881Spetersvn_diff__tree_processor_filter_create(const svn_diff_tree_processor_t * processor, 890251881Speter const char *prefix_relpath, 891251881Speter apr_pool_t *result_pool) 892251881Speter{ 893251881Speter struct filter_tree_baton_t *fb; 894251881Speter svn_diff_tree_processor_t *filter; 895251881Speter 896251881Speter fb = apr_pcalloc(result_pool, sizeof(*fb)); 897251881Speter fb->processor = processor; 898251881Speter if (prefix_relpath) 899251881Speter fb->prefix_relpath = apr_pstrdup(result_pool, prefix_relpath); 900251881Speter 901251881Speter filter = svn_diff__tree_processor_create(fb, result_pool); 902251881Speter 903251881Speter filter->dir_opened = filter_dir_opened; 904251881Speter filter->dir_added = filter_dir_added; 905251881Speter filter->dir_deleted = filter_dir_deleted; 906251881Speter filter->dir_changed = filter_dir_changed; 907251881Speter filter->dir_closed = filter_dir_closed; 908251881Speter 909251881Speter filter->file_opened = filter_file_opened; 910251881Speter filter->file_added = filter_file_added; 911251881Speter filter->file_deleted = filter_file_deleted; 912251881Speter filter->file_changed = filter_file_changed; 913251881Speter filter->file_closed = filter_file_closed; 914251881Speter 915251881Speter filter->node_absent = filter_node_absent; 916251881Speter 917251881Speter return filter; 918251881Speter} 919251881Speter 920251881Speterstruct copy_as_changed_baton_t 921251881Speter{ 922251881Speter const svn_diff_tree_processor_t *processor; 923251881Speter}; 924251881Speter 925251881Speterstatic svn_error_t * 926251881Spetercopy_as_changed_dir_opened(void **new_dir_baton, 927251881Speter svn_boolean_t *skip, 928251881Speter svn_boolean_t *skip_children, 929251881Speter const char *relpath, 930251881Speter const svn_diff_source_t *left_source, 931251881Speter const svn_diff_source_t *right_source, 932251881Speter const svn_diff_source_t *copyfrom_source, 933251881Speter void *parent_dir_baton, 934251881Speter const svn_diff_tree_processor_t *processor, 935251881Speter apr_pool_t *result_pool, 936251881Speter apr_pool_t *scratch_pool) 937251881Speter{ 938251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 939251881Speter 940251881Speter if (!left_source && copyfrom_source) 941251881Speter { 942251881Speter assert(right_source != NULL); 943251881Speter 944251881Speter left_source = copyfrom_source; 945251881Speter copyfrom_source = NULL; 946251881Speter } 947251881Speter 948251881Speter SVN_ERR(cb->processor->dir_opened(new_dir_baton, skip, skip_children, 949251881Speter relpath, 950251881Speter left_source, right_source, 951251881Speter copyfrom_source, 952251881Speter parent_dir_baton, 953251881Speter cb->processor, 954251881Speter result_pool, scratch_pool)); 955251881Speter return SVN_NO_ERROR; 956251881Speter} 957251881Speter 958251881Speterstatic svn_error_t * 959251881Spetercopy_as_changed_dir_added(const char *relpath, 960251881Speter const svn_diff_source_t *copyfrom_source, 961251881Speter const svn_diff_source_t *right_source, 962251881Speter /*const*/ apr_hash_t *copyfrom_props, 963251881Speter /*const*/ apr_hash_t *right_props, 964251881Speter void *dir_baton, 965251881Speter const svn_diff_tree_processor_t *processor, 966251881Speter apr_pool_t *scratch_pool) 967251881Speter{ 968251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 969251881Speter 970251881Speter if (copyfrom_source) 971251881Speter { 972251881Speter apr_array_header_t *propchanges; 973251881Speter SVN_ERR(svn_prop_diffs(&propchanges, right_props, copyfrom_props, 974251881Speter scratch_pool)); 975251881Speter SVN_ERR(cb->processor->dir_changed(relpath, 976251881Speter copyfrom_source, 977251881Speter right_source, 978251881Speter copyfrom_props, 979251881Speter right_props, 980251881Speter propchanges, 981251881Speter dir_baton, 982251881Speter cb->processor, 983251881Speter scratch_pool)); 984251881Speter } 985251881Speter else 986251881Speter { 987251881Speter SVN_ERR(cb->processor->dir_added(relpath, 988251881Speter copyfrom_source, 989251881Speter right_source, 990251881Speter copyfrom_props, 991251881Speter right_props, 992251881Speter dir_baton, 993251881Speter cb->processor, 994251881Speter scratch_pool)); 995251881Speter } 996251881Speter 997251881Speter return SVN_NO_ERROR; 998251881Speter} 999251881Speter 1000251881Speterstatic svn_error_t * 1001251881Spetercopy_as_changed_dir_deleted(const char *relpath, 1002251881Speter const svn_diff_source_t *left_source, 1003251881Speter /*const*/ apr_hash_t *left_props, 1004251881Speter void *dir_baton, 1005251881Speter const svn_diff_tree_processor_t *processor, 1006251881Speter apr_pool_t *scratch_pool) 1007251881Speter{ 1008251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1009251881Speter 1010251881Speter SVN_ERR(cb->processor->dir_deleted(relpath, 1011251881Speter left_source, 1012251881Speter left_props, 1013251881Speter dir_baton, 1014251881Speter cb->processor, 1015251881Speter scratch_pool)); 1016251881Speter 1017251881Speter return SVN_NO_ERROR; 1018251881Speter} 1019251881Speter 1020251881Speterstatic svn_error_t * 1021251881Spetercopy_as_changed_dir_changed(const char *relpath, 1022251881Speter const svn_diff_source_t *left_source, 1023251881Speter const svn_diff_source_t *right_source, 1024251881Speter /*const*/ apr_hash_t *left_props, 1025251881Speter /*const*/ apr_hash_t *right_props, 1026251881Speter const apr_array_header_t *prop_changes, 1027251881Speter void *dir_baton, 1028251881Speter const struct svn_diff_tree_processor_t *processor, 1029251881Speter apr_pool_t *scratch_pool) 1030251881Speter{ 1031251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1032251881Speter 1033251881Speter SVN_ERR(cb->processor->dir_changed(relpath, 1034251881Speter left_source, 1035251881Speter right_source, 1036251881Speter left_props, 1037251881Speter right_props, 1038251881Speter prop_changes, 1039251881Speter dir_baton, 1040251881Speter cb->processor, 1041251881Speter scratch_pool)); 1042251881Speter return SVN_NO_ERROR; 1043251881Speter} 1044251881Speter 1045251881Speterstatic svn_error_t * 1046251881Spetercopy_as_changed_dir_closed(const char *relpath, 1047251881Speter const svn_diff_source_t *left_source, 1048251881Speter const svn_diff_source_t *right_source, 1049251881Speter void *dir_baton, 1050251881Speter const svn_diff_tree_processor_t *processor, 1051251881Speter apr_pool_t *scratch_pool) 1052251881Speter{ 1053251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1054251881Speter 1055251881Speter SVN_ERR(cb->processor->dir_closed(relpath, 1056251881Speter left_source, 1057251881Speter right_source, 1058251881Speter dir_baton, 1059251881Speter cb->processor, 1060251881Speter scratch_pool)); 1061251881Speter return SVN_NO_ERROR; 1062251881Speter} 1063251881Speter 1064251881Speterstatic svn_error_t * 1065251881Spetercopy_as_changed_file_opened(void **new_file_baton, 1066251881Speter svn_boolean_t *skip, 1067251881Speter const char *relpath, 1068251881Speter const svn_diff_source_t *left_source, 1069251881Speter const svn_diff_source_t *right_source, 1070251881Speter const svn_diff_source_t *copyfrom_source, 1071251881Speter void *dir_baton, 1072251881Speter const svn_diff_tree_processor_t *processor, 1073251881Speter apr_pool_t *result_pool, 1074251881Speter apr_pool_t *scratch_pool) 1075251881Speter{ 1076251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1077251881Speter 1078251881Speter if (!left_source && copyfrom_source) 1079251881Speter { 1080251881Speter assert(right_source != NULL); 1081251881Speter 1082251881Speter left_source = copyfrom_source; 1083251881Speter copyfrom_source = NULL; 1084251881Speter } 1085251881Speter 1086251881Speter SVN_ERR(cb->processor->file_opened(new_file_baton, 1087251881Speter skip, 1088251881Speter relpath, 1089251881Speter left_source, 1090251881Speter right_source, 1091251881Speter copyfrom_source, 1092251881Speter dir_baton, 1093251881Speter cb->processor, 1094251881Speter result_pool, 1095251881Speter scratch_pool)); 1096251881Speter return SVN_NO_ERROR; 1097251881Speter} 1098251881Speter 1099251881Speterstatic svn_error_t * 1100251881Spetercopy_as_changed_file_added(const char *relpath, 1101251881Speter const svn_diff_source_t *copyfrom_source, 1102251881Speter const svn_diff_source_t *right_source, 1103251881Speter const char *copyfrom_file, 1104251881Speter const char *right_file, 1105251881Speter /*const*/ apr_hash_t *copyfrom_props, 1106251881Speter /*const*/ apr_hash_t *right_props, 1107251881Speter void *file_baton, 1108251881Speter const svn_diff_tree_processor_t *processor, 1109251881Speter apr_pool_t *scratch_pool) 1110251881Speter{ 1111251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1112251881Speter 1113251881Speter if (copyfrom_source) 1114251881Speter { 1115251881Speter apr_array_header_t *propchanges; 1116251881Speter svn_boolean_t same; 1117251881Speter SVN_ERR(svn_prop_diffs(&propchanges, right_props, copyfrom_props, 1118251881Speter scratch_pool)); 1119251881Speter 1120251881Speter /* "" is sometimes a marker for just modified (E.g. no-textdeltas), 1121251881Speter and it is certainly not a file */ 1122251881Speter if (*copyfrom_file && *right_file) 1123251881Speter { 1124251881Speter SVN_ERR(svn_io_files_contents_same_p(&same, copyfrom_file, 1125251881Speter right_file, scratch_pool)); 1126251881Speter } 1127251881Speter else 1128251881Speter same = FALSE; 1129251881Speter 1130251881Speter SVN_ERR(cb->processor->file_changed(relpath, 1131251881Speter copyfrom_source, 1132251881Speter right_source, 1133251881Speter copyfrom_file, 1134251881Speter right_file, 1135251881Speter copyfrom_props, 1136251881Speter right_props, 1137251881Speter !same, 1138251881Speter propchanges, 1139251881Speter file_baton, 1140251881Speter cb->processor, 1141251881Speter scratch_pool)); 1142251881Speter } 1143251881Speter else 1144251881Speter { 1145251881Speter SVN_ERR(cb->processor->file_added(relpath, 1146251881Speter copyfrom_source, 1147251881Speter right_source, 1148251881Speter copyfrom_file, 1149251881Speter right_file, 1150251881Speter copyfrom_props, 1151251881Speter right_props, 1152251881Speter file_baton, 1153251881Speter cb->processor, 1154251881Speter scratch_pool)); 1155251881Speter } 1156251881Speter return SVN_NO_ERROR; 1157251881Speter} 1158251881Speter 1159251881Speterstatic svn_error_t * 1160251881Spetercopy_as_changed_file_deleted(const char *relpath, 1161251881Speter const svn_diff_source_t *left_source, 1162251881Speter const char *left_file, 1163251881Speter /*const*/ apr_hash_t *left_props, 1164251881Speter void *file_baton, 1165251881Speter const svn_diff_tree_processor_t *processor, 1166251881Speter apr_pool_t *scratch_pool) 1167251881Speter{ 1168251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1169251881Speter 1170251881Speter SVN_ERR(cb->processor->file_deleted(relpath, 1171251881Speter left_source, 1172251881Speter left_file, 1173251881Speter left_props, 1174251881Speter file_baton, 1175251881Speter cb->processor, 1176251881Speter scratch_pool)); 1177251881Speter 1178251881Speter return SVN_NO_ERROR; 1179251881Speter} 1180251881Speter 1181251881Speterstatic svn_error_t * 1182251881Spetercopy_as_changed_file_changed(const char *relpath, 1183251881Speter const svn_diff_source_t *left_source, 1184251881Speter const svn_diff_source_t *right_source, 1185251881Speter const char *left_file, 1186251881Speter const char *right_file, 1187251881Speter /*const*/ apr_hash_t *left_props, 1188251881Speter /*const*/ apr_hash_t *right_props, 1189251881Speter svn_boolean_t file_modified, 1190251881Speter const apr_array_header_t *prop_changes, 1191251881Speter void *file_baton, 1192251881Speter const svn_diff_tree_processor_t *processor, 1193251881Speter apr_pool_t *scratch_pool) 1194251881Speter{ 1195251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1196251881Speter 1197251881Speter SVN_ERR(cb->processor->file_changed(relpath, 1198251881Speter left_source, 1199251881Speter right_source, 1200251881Speter left_file, 1201251881Speter right_file, 1202251881Speter left_props, 1203251881Speter right_props, 1204251881Speter file_modified, 1205251881Speter prop_changes, 1206251881Speter file_baton, 1207251881Speter cb->processor, 1208251881Speter scratch_pool)); 1209251881Speter return SVN_NO_ERROR; 1210251881Speter} 1211251881Speter 1212251881Speterstatic svn_error_t * 1213251881Spetercopy_as_changed_file_closed(const char *relpath, 1214251881Speter const svn_diff_source_t *left_source, 1215251881Speter const svn_diff_source_t *right_source, 1216251881Speter void *file_baton, 1217251881Speter const svn_diff_tree_processor_t *processor, 1218251881Speter apr_pool_t *scratch_pool) 1219251881Speter{ 1220251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1221251881Speter 1222251881Speter SVN_ERR(cb->processor->file_closed(relpath, 1223251881Speter left_source, 1224251881Speter right_source, 1225251881Speter file_baton, 1226251881Speter cb->processor, 1227251881Speter scratch_pool)); 1228251881Speter 1229251881Speter return SVN_NO_ERROR; 1230251881Speter} 1231251881Speter 1232251881Speterstatic svn_error_t * 1233251881Spetercopy_as_changed_node_absent(const char *relpath, 1234251881Speter void *dir_baton, 1235251881Speter const svn_diff_tree_processor_t *processor, 1236251881Speter apr_pool_t *scratch_pool) 1237251881Speter{ 1238251881Speter struct copy_as_changed_baton_t *cb = processor->baton; 1239251881Speter 1240251881Speter SVN_ERR(cb->processor->node_absent(relpath, 1241251881Speter dir_baton, 1242251881Speter cb->processor, 1243251881Speter scratch_pool)); 1244251881Speter return SVN_NO_ERROR; 1245251881Speter} 1246251881Speter 1247251881Speter 1248251881Speterconst svn_diff_tree_processor_t * 1249251881Spetersvn_diff__tree_processor_copy_as_changed_create( 1250251881Speter const svn_diff_tree_processor_t * processor, 1251251881Speter apr_pool_t *result_pool) 1252251881Speter{ 1253251881Speter struct copy_as_changed_baton_t *cb; 1254251881Speter svn_diff_tree_processor_t *filter; 1255251881Speter 1256251881Speter cb = apr_pcalloc(result_pool, sizeof(*cb)); 1257251881Speter cb->processor = processor; 1258251881Speter 1259251881Speter filter = svn_diff__tree_processor_create(cb, result_pool); 1260251881Speter filter->dir_opened = copy_as_changed_dir_opened; 1261251881Speter filter->dir_added = copy_as_changed_dir_added; 1262251881Speter filter->dir_deleted = copy_as_changed_dir_deleted; 1263251881Speter filter->dir_changed = copy_as_changed_dir_changed; 1264251881Speter filter->dir_closed = copy_as_changed_dir_closed; 1265251881Speter 1266251881Speter filter->file_opened = copy_as_changed_file_opened; 1267251881Speter filter->file_added = copy_as_changed_file_added; 1268251881Speter filter->file_deleted = copy_as_changed_file_deleted; 1269251881Speter filter->file_changed = copy_as_changed_file_changed; 1270251881Speter filter->file_closed = copy_as_changed_file_closed; 1271251881Speter 1272251881Speter filter->node_absent = copy_as_changed_node_absent; 1273251881Speter 1274251881Speter return filter; 1275251881Speter} 1276251881Speter 1277251881Speter 1278251881Speter/* Processor baton for the tee tree processor */ 1279251881Speterstruct tee_baton_t 1280251881Speter{ 1281251881Speter const svn_diff_tree_processor_t *p1; 1282251881Speter const svn_diff_tree_processor_t *p2; 1283251881Speter}; 1284251881Speter 1285251881Speter/* Wrapper baton for file and directory batons in the tee processor */ 1286251881Speterstruct tee_node_baton_t 1287251881Speter{ 1288251881Speter void *baton1; 1289251881Speter void *baton2; 1290251881Speter}; 1291251881Speter 1292251881Speterstatic svn_error_t * 1293251881Spetertee_dir_opened(void **new_dir_baton, 1294251881Speter svn_boolean_t *skip, 1295251881Speter svn_boolean_t *skip_children, 1296251881Speter const char *relpath, 1297251881Speter const svn_diff_source_t *left_source, 1298251881Speter const svn_diff_source_t *right_source, 1299251881Speter const svn_diff_source_t *copyfrom_source, 1300251881Speter void *parent_dir_baton, 1301251881Speter const svn_diff_tree_processor_t *processor, 1302251881Speter apr_pool_t *result_pool, 1303251881Speter apr_pool_t *scratch_pool) 1304251881Speter{ 1305251881Speter struct tee_baton_t *tb = processor->baton; 1306251881Speter struct tee_node_baton_t *pb = parent_dir_baton; 1307251881Speter struct tee_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb)); 1308251881Speter 1309251881Speter SVN_ERR(tb->p1->dir_opened(&(nb->baton1), 1310251881Speter skip, 1311251881Speter skip_children, 1312251881Speter relpath, 1313251881Speter left_source, 1314251881Speter right_source, 1315251881Speter copyfrom_source, 1316251881Speter pb ? pb->baton1 : NULL, 1317251881Speter tb->p1, 1318251881Speter result_pool, 1319251881Speter scratch_pool)); 1320251881Speter 1321251881Speter SVN_ERR(tb->p2->dir_opened(&(nb->baton2), 1322251881Speter skip, 1323251881Speter skip_children, 1324251881Speter relpath, 1325251881Speter left_source, 1326251881Speter right_source, 1327251881Speter copyfrom_source, 1328251881Speter pb ? pb->baton2 : NULL, 1329251881Speter tb->p2, 1330251881Speter result_pool, 1331251881Speter scratch_pool)); 1332251881Speter 1333251881Speter *new_dir_baton = nb; 1334251881Speter 1335251881Speter return SVN_NO_ERROR; 1336251881Speter} 1337251881Speter 1338251881Speterstatic svn_error_t * 1339251881Spetertee_dir_added(const char *relpath, 1340251881Speter const svn_diff_source_t *copyfrom_source, 1341251881Speter const svn_diff_source_t *right_source, 1342251881Speter /*const*/ apr_hash_t *copyfrom_props, 1343251881Speter /*const*/ apr_hash_t *right_props, 1344251881Speter void *dir_baton, 1345251881Speter const svn_diff_tree_processor_t *processor, 1346251881Speter apr_pool_t *scratch_pool) 1347251881Speter{ 1348251881Speter struct tee_baton_t *tb = processor->baton; 1349251881Speter struct tee_node_baton_t *db = dir_baton; 1350251881Speter 1351251881Speter SVN_ERR(tb->p1->dir_added(relpath, 1352251881Speter copyfrom_source, 1353251881Speter right_source, 1354251881Speter copyfrom_props, 1355251881Speter right_props, 1356251881Speter db->baton1, 1357251881Speter tb->p1, 1358251881Speter scratch_pool)); 1359251881Speter 1360251881Speter SVN_ERR(tb->p2->dir_added(relpath, 1361251881Speter copyfrom_source, 1362251881Speter right_source, 1363251881Speter copyfrom_props, 1364251881Speter right_props, 1365251881Speter db->baton2, 1366251881Speter tb->p2, 1367251881Speter scratch_pool)); 1368251881Speter 1369251881Speter return SVN_NO_ERROR; 1370251881Speter} 1371251881Speter 1372251881Speterstatic svn_error_t * 1373251881Spetertee_dir_deleted(const char *relpath, 1374251881Speter const svn_diff_source_t *left_source, 1375251881Speter /*const*/ apr_hash_t *left_props, 1376251881Speter void *dir_baton, 1377251881Speter const svn_diff_tree_processor_t *processor, 1378251881Speter apr_pool_t *scratch_pool) 1379251881Speter{ 1380251881Speter struct tee_baton_t *tb = processor->baton; 1381251881Speter struct tee_node_baton_t *db = dir_baton; 1382251881Speter 1383251881Speter SVN_ERR(tb->p1->dir_deleted(relpath, 1384251881Speter left_source, 1385251881Speter left_props, 1386251881Speter db->baton1, 1387251881Speter tb->p1, 1388251881Speter scratch_pool)); 1389251881Speter 1390251881Speter SVN_ERR(tb->p2->dir_deleted(relpath, 1391251881Speter left_source, 1392251881Speter left_props, 1393251881Speter db->baton2, 1394251881Speter tb->p2, 1395251881Speter scratch_pool)); 1396251881Speter 1397251881Speter return SVN_NO_ERROR; 1398251881Speter} 1399251881Speter 1400251881Speterstatic svn_error_t * 1401251881Spetertee_dir_changed(const char *relpath, 1402251881Speter const svn_diff_source_t *left_source, 1403251881Speter const svn_diff_source_t *right_source, 1404251881Speter /*const*/ apr_hash_t *left_props, 1405251881Speter /*const*/ apr_hash_t *right_props, 1406251881Speter const apr_array_header_t *prop_changes, 1407251881Speter void *dir_baton, 1408251881Speter const struct svn_diff_tree_processor_t *processor, 1409251881Speter apr_pool_t *scratch_pool) 1410251881Speter{ 1411251881Speter struct tee_baton_t *tb = processor->baton; 1412251881Speter struct tee_node_baton_t *db = dir_baton; 1413251881Speter 1414251881Speter SVN_ERR(tb->p1->dir_changed(relpath, 1415251881Speter left_source, 1416251881Speter right_source, 1417251881Speter left_props, 1418251881Speter right_props, 1419251881Speter prop_changes, 1420251881Speter db->baton1, 1421251881Speter tb->p1, 1422251881Speter scratch_pool)); 1423251881Speter 1424251881Speter SVN_ERR(tb->p2->dir_changed(relpath, 1425251881Speter left_source, 1426251881Speter right_source, 1427251881Speter left_props, 1428251881Speter right_props, 1429251881Speter prop_changes, 1430251881Speter db->baton2, 1431251881Speter tb->p2, 1432251881Speter scratch_pool)); 1433251881Speter return SVN_NO_ERROR; 1434251881Speter} 1435251881Speter 1436251881Speterstatic svn_error_t * 1437251881Spetertee_dir_closed(const char *relpath, 1438251881Speter const svn_diff_source_t *left_source, 1439251881Speter const svn_diff_source_t *right_source, 1440251881Speter void *dir_baton, 1441251881Speter const svn_diff_tree_processor_t *processor, 1442251881Speter apr_pool_t *scratch_pool) 1443251881Speter{ 1444251881Speter struct tee_baton_t *tb = processor->baton; 1445251881Speter struct tee_node_baton_t *db = dir_baton; 1446251881Speter 1447251881Speter SVN_ERR(tb->p1->dir_closed(relpath, 1448251881Speter left_source, 1449251881Speter right_source, 1450251881Speter db->baton1, 1451251881Speter tb->p1, 1452251881Speter scratch_pool)); 1453251881Speter 1454251881Speter SVN_ERR(tb->p2->dir_closed(relpath, 1455251881Speter left_source, 1456251881Speter right_source, 1457251881Speter db->baton2, 1458251881Speter tb->p2, 1459251881Speter scratch_pool)); 1460251881Speter return SVN_NO_ERROR; 1461251881Speter} 1462251881Speter 1463251881Speterstatic svn_error_t * 1464251881Spetertee_file_opened(void **new_file_baton, 1465251881Speter svn_boolean_t *skip, 1466251881Speter const char *relpath, 1467251881Speter const svn_diff_source_t *left_source, 1468251881Speter const svn_diff_source_t *right_source, 1469251881Speter const svn_diff_source_t *copyfrom_source, 1470251881Speter void *dir_baton, 1471251881Speter const svn_diff_tree_processor_t *processor, 1472251881Speter apr_pool_t *result_pool, 1473251881Speter apr_pool_t *scratch_pool) 1474251881Speter{ 1475251881Speter struct tee_baton_t *tb = processor->baton; 1476251881Speter struct tee_node_baton_t *pb = dir_baton; 1477251881Speter struct tee_node_baton_t *nb = apr_pcalloc(result_pool, sizeof(*nb)); 1478251881Speter 1479251881Speter SVN_ERR(tb->p1->file_opened(&(nb->baton1), 1480251881Speter skip, 1481251881Speter relpath, 1482251881Speter left_source, 1483251881Speter right_source, 1484251881Speter copyfrom_source, 1485251881Speter pb ? pb->baton1 : NULL, 1486251881Speter tb->p1, 1487251881Speter result_pool, 1488251881Speter scratch_pool)); 1489251881Speter 1490251881Speter SVN_ERR(tb->p2->file_opened(&(nb->baton2), 1491251881Speter skip, 1492251881Speter relpath, 1493251881Speter left_source, 1494251881Speter right_source, 1495251881Speter copyfrom_source, 1496251881Speter pb ? pb->baton2 : NULL, 1497251881Speter tb->p2, 1498251881Speter result_pool, 1499251881Speter scratch_pool)); 1500251881Speter 1501251881Speter *new_file_baton = nb; 1502251881Speter 1503251881Speter return SVN_NO_ERROR; 1504251881Speter} 1505251881Speter 1506251881Speterstatic svn_error_t * 1507251881Spetertee_file_added(const char *relpath, 1508251881Speter const svn_diff_source_t *copyfrom_source, 1509251881Speter const svn_diff_source_t *right_source, 1510251881Speter const char *copyfrom_file, 1511251881Speter const char *right_file, 1512251881Speter /*const*/ apr_hash_t *copyfrom_props, 1513251881Speter /*const*/ apr_hash_t *right_props, 1514251881Speter void *file_baton, 1515251881Speter const svn_diff_tree_processor_t *processor, 1516251881Speter apr_pool_t *scratch_pool) 1517251881Speter{ 1518251881Speter struct tee_baton_t *tb = processor->baton; 1519251881Speter struct tee_node_baton_t *fb = file_baton; 1520251881Speter 1521251881Speter SVN_ERR(tb->p1->file_added(relpath, 1522251881Speter copyfrom_source, 1523251881Speter right_source, 1524251881Speter copyfrom_file, 1525251881Speter right_file, 1526251881Speter copyfrom_props, 1527251881Speter right_props, 1528251881Speter fb->baton1, 1529251881Speter tb->p1, 1530251881Speter scratch_pool)); 1531251881Speter 1532251881Speter SVN_ERR(tb->p2->file_added(relpath, 1533251881Speter copyfrom_source, 1534251881Speter right_source, 1535251881Speter copyfrom_file, 1536251881Speter right_file, 1537251881Speter copyfrom_props, 1538251881Speter right_props, 1539251881Speter fb->baton2, 1540251881Speter tb->p2, 1541251881Speter scratch_pool)); 1542251881Speter return SVN_NO_ERROR; 1543251881Speter} 1544251881Speter 1545251881Speterstatic svn_error_t * 1546251881Spetertee_file_deleted(const char *relpath, 1547251881Speter const svn_diff_source_t *left_source, 1548251881Speter const char *left_file, 1549251881Speter /*const*/ apr_hash_t *left_props, 1550251881Speter void *file_baton, 1551251881Speter const svn_diff_tree_processor_t *processor, 1552251881Speter apr_pool_t *scratch_pool) 1553251881Speter{ 1554251881Speter struct tee_baton_t *tb = processor->baton; 1555251881Speter struct tee_node_baton_t *fb = file_baton; 1556251881Speter 1557251881Speter SVN_ERR(tb->p1->file_deleted(relpath, 1558251881Speter left_source, 1559251881Speter left_file, 1560251881Speter left_props, 1561251881Speter fb->baton1, 1562251881Speter tb->p1, 1563251881Speter scratch_pool)); 1564251881Speter 1565251881Speter SVN_ERR(tb->p2->file_deleted(relpath, 1566251881Speter left_source, 1567251881Speter left_file, 1568251881Speter left_props, 1569251881Speter fb->baton2, 1570251881Speter tb->p2, 1571251881Speter scratch_pool)); 1572251881Speter return SVN_NO_ERROR; 1573251881Speter} 1574251881Speter 1575251881Speterstatic svn_error_t * 1576251881Spetertee_file_changed(const char *relpath, 1577251881Speter const svn_diff_source_t *left_source, 1578251881Speter const svn_diff_source_t *right_source, 1579251881Speter const char *left_file, 1580251881Speter const char *right_file, 1581251881Speter /*const*/ apr_hash_t *left_props, 1582251881Speter /*const*/ apr_hash_t *right_props, 1583251881Speter svn_boolean_t file_modified, 1584251881Speter const apr_array_header_t *prop_changes, 1585251881Speter void *file_baton, 1586251881Speter const svn_diff_tree_processor_t *processor, 1587251881Speter apr_pool_t *scratch_pool) 1588251881Speter{ 1589251881Speter struct tee_baton_t *tb = processor->baton; 1590251881Speter struct tee_node_baton_t *fb = file_baton; 1591251881Speter 1592251881Speter SVN_ERR(tb->p1->file_changed(relpath, 1593251881Speter left_source, 1594251881Speter right_source, 1595251881Speter left_file, 1596251881Speter right_file, 1597251881Speter left_props, 1598251881Speter right_props, 1599251881Speter file_modified, 1600251881Speter prop_changes, 1601251881Speter fb->baton1, 1602251881Speter tb->p1, 1603251881Speter scratch_pool)); 1604251881Speter 1605251881Speter SVN_ERR(tb->p2->file_changed(relpath, 1606251881Speter left_source, 1607251881Speter right_source, 1608251881Speter left_file, 1609251881Speter right_file, 1610251881Speter left_props, 1611251881Speter right_props, 1612251881Speter file_modified, 1613251881Speter prop_changes, 1614251881Speter fb->baton2, 1615251881Speter tb->p2, 1616251881Speter scratch_pool)); 1617251881Speter return SVN_NO_ERROR; 1618251881Speter} 1619251881Speter 1620251881Speterstatic svn_error_t * 1621251881Spetertee_file_closed(const char *relpath, 1622251881Speter const svn_diff_source_t *left_source, 1623251881Speter const svn_diff_source_t *right_source, 1624251881Speter void *file_baton, 1625251881Speter const svn_diff_tree_processor_t *processor, 1626251881Speter apr_pool_t *scratch_pool) 1627251881Speter{ 1628251881Speter struct tee_baton_t *tb = processor->baton; 1629251881Speter struct tee_node_baton_t *fb = file_baton; 1630251881Speter 1631251881Speter SVN_ERR(tb->p1->file_closed(relpath, 1632251881Speter left_source, 1633251881Speter right_source, 1634251881Speter fb->baton1, 1635251881Speter tb->p1, 1636251881Speter scratch_pool)); 1637251881Speter 1638251881Speter SVN_ERR(tb->p2->file_closed(relpath, 1639251881Speter left_source, 1640251881Speter right_source, 1641251881Speter fb->baton2, 1642251881Speter tb->p2, 1643251881Speter scratch_pool)); 1644251881Speter 1645251881Speter return SVN_NO_ERROR; 1646251881Speter} 1647251881Speter 1648251881Speterstatic svn_error_t * 1649251881Spetertee_node_absent(const char *relpath, 1650251881Speter void *dir_baton, 1651251881Speter const svn_diff_tree_processor_t *processor, 1652251881Speter apr_pool_t *scratch_pool) 1653251881Speter{ 1654251881Speter struct tee_baton_t *tb = processor->baton; 1655251881Speter struct tee_node_baton_t *db = dir_baton; 1656251881Speter 1657251881Speter SVN_ERR(tb->p1->node_absent(relpath, 1658251881Speter db ? db->baton1 : NULL, 1659251881Speter tb->p1, 1660251881Speter scratch_pool)); 1661251881Speter 1662251881Speter SVN_ERR(tb->p2->node_absent(relpath, 1663251881Speter db ? db->baton2 : NULL, 1664251881Speter tb->p2, 1665251881Speter scratch_pool)); 1666251881Speter 1667251881Speter return SVN_NO_ERROR; 1668251881Speter} 1669251881Speter 1670251881Speterconst svn_diff_tree_processor_t * 1671251881Spetersvn_diff__tree_processor_tee_create(const svn_diff_tree_processor_t *processor1, 1672251881Speter const svn_diff_tree_processor_t *processor2, 1673251881Speter apr_pool_t *result_pool) 1674251881Speter{ 1675251881Speter struct tee_baton_t *tb = apr_pcalloc(result_pool, sizeof(*tb)); 1676251881Speter svn_diff_tree_processor_t *tee; 1677251881Speter tb->p1 = processor1; 1678251881Speter tb->p2 = processor2; 1679251881Speter 1680251881Speter tee = svn_diff__tree_processor_create(tb, result_pool); 1681251881Speter 1682251881Speter tee->dir_opened = tee_dir_opened; 1683251881Speter tee->dir_added = tee_dir_added; 1684251881Speter tee->dir_deleted = tee_dir_deleted; 1685251881Speter tee->dir_changed = tee_dir_changed; 1686251881Speter tee->dir_closed = tee_dir_closed; 1687251881Speter tee->file_opened = tee_file_opened; 1688251881Speter tee->file_added = tee_file_added; 1689251881Speter tee->file_deleted = tee_file_deleted; 1690251881Speter tee->file_changed = tee_file_changed; 1691251881Speter tee->file_closed = tee_file_closed; 1692251881Speter tee->node_absent = tee_node_absent; 1693251881Speter 1694251881Speter return tee; 1695251881Speter} 1696251881Speter 1697251881Spetersvn_diff_source_t * 1698251881Spetersvn_diff__source_create(svn_revnum_t revision, 1699251881Speter apr_pool_t *result_pool) 1700251881Speter{ 1701251881Speter svn_diff_source_t *src = apr_pcalloc(result_pool, sizeof(*src)); 1702251881Speter 1703251881Speter src->revision = revision; 1704251881Speter return src; 1705251881Speter} 1706