1251881Speter/* 2251881Speter * ambient_depth_filter_editor.c -- provide a svn_delta_editor_t which wraps 3251881Speter * another editor and provides 4251881Speter * *ambient* depth-based filtering 5251881Speter * 6251881Speter * ==================================================================== 7251881Speter * Licensed to the Apache Software Foundation (ASF) under one 8251881Speter * or more contributor license agreements. See the NOTICE file 9251881Speter * distributed with this work for additional information 10251881Speter * regarding copyright ownership. The ASF licenses this file 11251881Speter * to you under the Apache License, Version 2.0 (the 12251881Speter * "License"); you may not use this file except in compliance 13251881Speter * with the License. You may obtain a copy of the License at 14251881Speter * 15251881Speter * http://www.apache.org/licenses/LICENSE-2.0 16251881Speter * 17251881Speter * Unless required by applicable law or agreed to in writing, 18251881Speter * software distributed under the License is distributed on an 19251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20251881Speter * KIND, either express or implied. See the License for the 21251881Speter * specific language governing permissions and limitations 22251881Speter * under the License. 23251881Speter * ==================================================================== 24251881Speter */ 25251881Speter 26251881Speter#include "svn_delta.h" 27251881Speter#include "svn_wc.h" 28251881Speter#include "svn_dirent_uri.h" 29251881Speter#include "svn_path.h" 30251881Speter 31251881Speter#include "wc.h" 32251881Speter 33251881Speter/* 34251881Speter Notes on the general depth-filtering strategy. 35251881Speter ============================================== 36251881Speter 37251881Speter When a depth-aware (>= 1.5) client pulls an update from a 38251881Speter non-depth-aware server, the server may send back too much data, 39251881Speter because it doesn't hear what the client tells it about the 40251881Speter "requested depth" of the update (the "foo" in "--depth=foo"), nor 41251881Speter about the "ambient depth" of each working copy directory. 42251881Speter 43251881Speter For example, suppose a 1.5 client does this against a 1.4 server: 44251881Speter 45251881Speter $ svn co --depth=empty -rSOME_OLD_REV http://url/repos/blah/ wc 46251881Speter $ cd wc 47251881Speter $ svn up 48251881Speter 49251881Speter In the initial checkout, the requested depth is 'empty', so the 50251881Speter depth-filtering editor (see libsvn_delta/depth_filter_editor.c) 51251881Speter that wraps the main update editor transparently filters out all 52251881Speter the unwanted calls. 53251881Speter 54251881Speter In the 'svn up', the requested depth is unspecified, meaning that 55251881Speter the ambient depth(s) of the working copy should be preserved. 56251881Speter Since there's only one directory, and its depth is 'empty', 57251881Speter clearly we should filter out or render no-ops all editor calls 58251881Speter after open_root(), except maybe for change_dir_prop() on the 59251881Speter top-level directory. (Note that the server will have stuff to 60251881Speter send down, because we checked out at an old revision in the first 61251881Speter place, to set up this scenario.) 62251881Speter 63251881Speter The depth-filtering editor won't help us here. It only filters 64251881Speter based on the requested depth, it never looks in the working copy 65251881Speter to get ambient depths. So the update editor itself will have to 66251881Speter filter out the unwanted calls -- or better yet, it will have to 67251881Speter be wrapped in a filtering editor that does the job. 68251881Speter 69251881Speter This is that filtering editor. 70251881Speter 71251881Speter Most of the work is done at the moment of baton construction. 72251881Speter When a file or dir is opened, we create its baton with the 73251881Speter appropriate ambient depth, either taking the depth directly from 74251881Speter the corresponding working copy object (if available), or from its 75251881Speter parent baton. In the latter case, we don't just copy the parent 76251881Speter baton's depth, but rather use it to choose the correct depth for 77251881Speter this child. The usual depth demotion rules apply, with the 78251881Speter additional stipulation that as soon as we find a subtree is not 79251881Speter present at all, due to being omitted for depth reasons, we set the 80251881Speter ambiently_excluded flag in its baton, which signals that 81251881Speter all descendant batons should be ignored. 82251881Speter (In fact, we may just re-use the parent baton, since none of the 83251881Speter other fields will be used anyway.) 84251881Speter 85251881Speter See issues #2842 and #2897 for more. 86251881Speter*/ 87251881Speter 88251881Speter 89251881Speter/*** Batons, and the Toys That Create Them ***/ 90251881Speter 91251881Speterstruct edit_baton 92251881Speter{ 93251881Speter const svn_delta_editor_t *wrapped_editor; 94251881Speter void *wrapped_edit_baton; 95251881Speter svn_wc__db_t *db; 96251881Speter const char *anchor_abspath; 97251881Speter const char *target; 98251881Speter}; 99251881Speter 100251881Speterstruct file_baton 101251881Speter{ 102251881Speter svn_boolean_t ambiently_excluded; 103251881Speter struct edit_baton *edit_baton; 104251881Speter void *wrapped_baton; 105251881Speter}; 106251881Speter 107251881Speterstruct dir_baton 108251881Speter{ 109251881Speter svn_boolean_t ambiently_excluded; 110251881Speter svn_depth_t ambient_depth; 111251881Speter struct edit_baton *edit_baton; 112251881Speter const char *abspath; 113251881Speter void *wrapped_baton; 114251881Speter}; 115251881Speter 116251881Speter/* Fetch the STATUS, KIND and DEPTH of the base node at LOCAL_ABSPATH. 117251881Speter * If there is no such base node, report 'normal', 'unknown' and 'unknown' 118251881Speter * respectively. 119251881Speter * 120251881Speter * STATUS and/or DEPTH may be NULL if not wanted; KIND must not be NULL. 121251881Speter */ 122251881Speterstatic svn_error_t * 123251881Speterambient_read_info(svn_wc__db_status_t *status, 124251881Speter svn_node_kind_t *kind, 125251881Speter svn_depth_t *depth, 126251881Speter svn_wc__db_t *db, 127251881Speter const char *local_abspath, 128251881Speter apr_pool_t *scratch_pool) 129251881Speter{ 130251881Speter svn_error_t *err; 131251881Speter SVN_ERR_ASSERT(kind != NULL); 132251881Speter 133251881Speter err = svn_wc__db_base_get_info(status, kind, NULL, NULL, NULL, NULL, 134251881Speter NULL, NULL, NULL, depth, NULL, NULL, 135251881Speter NULL, NULL, NULL, NULL, 136251881Speter db, local_abspath, 137251881Speter scratch_pool, scratch_pool); 138251881Speter 139251881Speter if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) 140251881Speter { 141251881Speter svn_error_clear(err); 142251881Speter 143251881Speter *kind = svn_node_unknown; 144251881Speter if (status) 145251881Speter *status = svn_wc__db_status_normal; 146251881Speter if (depth) 147251881Speter *depth = svn_depth_unknown; 148251881Speter 149251881Speter return SVN_NO_ERROR; 150251881Speter } 151251881Speter else 152251881Speter SVN_ERR(err); 153251881Speter 154251881Speter return SVN_NO_ERROR; 155251881Speter} 156251881Speter 157251881Speter/* */ 158251881Speterstatic svn_error_t * 159251881Spetermake_dir_baton(struct dir_baton **d_p, 160251881Speter const char *path, 161251881Speter struct edit_baton *eb, 162251881Speter struct dir_baton *pb, 163251881Speter svn_boolean_t added, 164251881Speter apr_pool_t *pool) 165251881Speter{ 166251881Speter struct dir_baton *d; 167251881Speter 168251881Speter SVN_ERR_ASSERT(path || (! pb)); 169251881Speter 170251881Speter if (pb && pb->ambiently_excluded) 171251881Speter { 172251881Speter /* Just re-use the parent baton, since the only field that 173251881Speter matters is ambiently_excluded. */ 174251881Speter *d_p = pb; 175251881Speter return SVN_NO_ERROR; 176251881Speter } 177251881Speter 178251881Speter /* Okay, no easy out, so allocate and initialize a dir baton. */ 179251881Speter d = apr_pcalloc(pool, sizeof(*d)); 180251881Speter 181251881Speter if (path) 182251881Speter d->abspath = svn_dirent_join(eb->anchor_abspath, path, pool); 183251881Speter else 184251881Speter d->abspath = apr_pstrdup(pool, eb->anchor_abspath); 185251881Speter 186251881Speter /* The svn_depth_unknown means that: 1) pb is the anchor; 2) there 187251881Speter is an non-null target, for which we are preparing the baton. 188251881Speter This enables explicitly pull in the target. */ 189251881Speter if (pb && pb->ambient_depth != svn_depth_unknown) 190251881Speter { 191251881Speter svn_boolean_t exclude; 192251881Speter svn_wc__db_status_t status; 193251881Speter svn_node_kind_t kind; 194251881Speter svn_boolean_t exists = TRUE; 195251881Speter 196251881Speter if (!added) 197251881Speter { 198251881Speter SVN_ERR(ambient_read_info(&status, &kind, NULL, 199251881Speter eb->db, d->abspath, pool)); 200251881Speter } 201251881Speter else 202251881Speter { 203251881Speter status = svn_wc__db_status_not_present; 204251881Speter kind = svn_node_unknown; 205251881Speter } 206251881Speter 207251881Speter exists = (kind != svn_node_unknown); 208251881Speter 209251881Speter if (pb->ambient_depth == svn_depth_empty 210251881Speter || pb->ambient_depth == svn_depth_files) 211251881Speter { 212251881Speter /* This is not a depth upgrade, and the parent directory is 213251881Speter depth==empty or depth==files. So if the parent doesn't 214251881Speter already have an entry for the new dir, then the parent 215251881Speter doesn't want the new dir at all, thus we should initialize 216251881Speter it with ambiently_excluded=TRUE. */ 217251881Speter exclude = !exists; 218251881Speter } 219251881Speter else 220251881Speter { 221251881Speter /* If the parent expect all children by default, only exclude 222251881Speter it whenever it is explicitly marked as exclude. */ 223251881Speter exclude = exists && (status == svn_wc__db_status_excluded); 224251881Speter } 225251881Speter if (exclude) 226251881Speter { 227251881Speter d->ambiently_excluded = TRUE; 228251881Speter *d_p = d; 229251881Speter return SVN_NO_ERROR; 230251881Speter } 231251881Speter } 232251881Speter 233251881Speter d->edit_baton = eb; 234251881Speter /* We'll initialize this differently in add_directory and 235251881Speter open_directory. */ 236251881Speter d->ambient_depth = svn_depth_unknown; 237251881Speter 238251881Speter *d_p = d; 239251881Speter return SVN_NO_ERROR; 240251881Speter} 241251881Speter 242251881Speter/* */ 243251881Speterstatic svn_error_t * 244251881Spetermake_file_baton(struct file_baton **f_p, 245251881Speter struct dir_baton *pb, 246251881Speter const char *path, 247251881Speter svn_boolean_t added, 248251881Speter apr_pool_t *pool) 249251881Speter{ 250251881Speter struct file_baton *f = apr_pcalloc(pool, sizeof(*f)); 251251881Speter struct edit_baton *eb = pb->edit_baton; 252251881Speter svn_wc__db_status_t status; 253251881Speter svn_node_kind_t kind; 254251881Speter const char *abspath; 255251881Speter 256251881Speter SVN_ERR_ASSERT(path); 257251881Speter 258251881Speter if (pb->ambiently_excluded) 259251881Speter { 260251881Speter f->ambiently_excluded = TRUE; 261251881Speter *f_p = f; 262251881Speter return SVN_NO_ERROR; 263251881Speter } 264251881Speter 265251881Speter abspath = svn_dirent_join(eb->anchor_abspath, path, pool); 266251881Speter 267251881Speter if (!added) 268251881Speter { 269251881Speter SVN_ERR(ambient_read_info(&status, &kind, NULL, 270251881Speter eb->db, abspath, pool)); 271251881Speter } 272251881Speter else 273251881Speter { 274251881Speter status = svn_wc__db_status_not_present; 275251881Speter kind = svn_node_unknown; 276251881Speter } 277251881Speter 278251881Speter if (pb->ambient_depth == svn_depth_empty) 279251881Speter { 280251881Speter /* This is not a depth upgrade, and the parent directory is 281251881Speter depth==empty. So if the parent doesn't 282251881Speter already have an entry for the file, then the parent 283251881Speter doesn't want to hear about the file at all. */ 284251881Speter 285251881Speter if (status == svn_wc__db_status_not_present 286251881Speter || status == svn_wc__db_status_server_excluded 287251881Speter || status == svn_wc__db_status_excluded 288251881Speter || kind == svn_node_unknown) 289251881Speter { 290251881Speter f->ambiently_excluded = TRUE; 291251881Speter *f_p = f; 292251881Speter return SVN_NO_ERROR; 293251881Speter } 294251881Speter } 295251881Speter 296251881Speter /* If pb->ambient_depth == svn_depth_unknown we are pulling 297251881Speter in new nodes */ 298251881Speter if (pb->ambient_depth != svn_depth_unknown 299251881Speter && status == svn_wc__db_status_excluded) 300251881Speter { 301251881Speter f->ambiently_excluded = TRUE; 302251881Speter *f_p = f; 303251881Speter return SVN_NO_ERROR; 304251881Speter } 305251881Speter 306251881Speter f->edit_baton = pb->edit_baton; 307251881Speter 308251881Speter *f_p = f; 309251881Speter return SVN_NO_ERROR; 310251881Speter} 311251881Speter 312251881Speter 313251881Speter/*** Editor Functions ***/ 314251881Speter 315251881Speter/* An svn_delta_editor_t function. */ 316251881Speterstatic svn_error_t * 317251881Speterset_target_revision(void *edit_baton, 318251881Speter svn_revnum_t target_revision, 319251881Speter apr_pool_t *pool) 320251881Speter{ 321251881Speter struct edit_baton *eb = edit_baton; 322251881Speter 323251881Speter /* Nothing depth-y to filter here. */ 324251881Speter return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, 325251881Speter target_revision, pool); 326251881Speter} 327251881Speter 328251881Speter/* An svn_delta_editor_t function. */ 329251881Speterstatic svn_error_t * 330251881Speteropen_root(void *edit_baton, 331251881Speter svn_revnum_t base_revision, 332251881Speter apr_pool_t *pool, 333251881Speter void **root_baton) 334251881Speter{ 335251881Speter struct edit_baton *eb = edit_baton; 336251881Speter struct dir_baton *b; 337251881Speter 338251881Speter SVN_ERR(make_dir_baton(&b, NULL, eb, NULL, FALSE, pool)); 339251881Speter *root_baton = b; 340251881Speter 341251881Speter if (b->ambiently_excluded) 342251881Speter return SVN_NO_ERROR; 343251881Speter 344251881Speter if (! *eb->target) 345251881Speter { 346251881Speter /* For an update with a NULL target, this is equivalent to open_dir(): */ 347251881Speter svn_node_kind_t kind; 348251881Speter svn_wc__db_status_t status; 349251881Speter svn_depth_t depth; 350251881Speter 351251881Speter /* Read the depth from the entry. */ 352251881Speter SVN_ERR(ambient_read_info(&status, &kind, &depth, 353251881Speter eb->db, eb->anchor_abspath, 354251881Speter pool)); 355251881Speter 356251881Speter if (kind != svn_node_unknown 357251881Speter && status != svn_wc__db_status_not_present 358251881Speter && status != svn_wc__db_status_excluded 359251881Speter && status != svn_wc__db_status_server_excluded) 360251881Speter { 361251881Speter b->ambient_depth = depth; 362251881Speter } 363251881Speter } 364251881Speter 365251881Speter return eb->wrapped_editor->open_root(eb->wrapped_edit_baton, base_revision, 366251881Speter pool, &b->wrapped_baton); 367251881Speter} 368251881Speter 369251881Speter/* An svn_delta_editor_t function. */ 370251881Speterstatic svn_error_t * 371251881Speterdelete_entry(const char *path, 372251881Speter svn_revnum_t base_revision, 373251881Speter void *parent_baton, 374251881Speter apr_pool_t *pool) 375251881Speter{ 376251881Speter struct dir_baton *pb = parent_baton; 377251881Speter struct edit_baton *eb = pb->edit_baton; 378251881Speter 379251881Speter if (pb->ambiently_excluded) 380251881Speter return SVN_NO_ERROR; 381251881Speter 382251881Speter if (pb->ambient_depth < svn_depth_immediates) 383251881Speter { 384251881Speter /* If the entry we want to delete doesn't exist, that's OK. 385251881Speter It's probably an old server that doesn't understand 386251881Speter depths. */ 387251881Speter svn_node_kind_t kind; 388251881Speter svn_wc__db_status_t status; 389251881Speter const char *abspath; 390251881Speter 391251881Speter abspath = svn_dirent_join(eb->anchor_abspath, path, pool); 392251881Speter 393251881Speter SVN_ERR(ambient_read_info(&status, &kind, NULL, 394251881Speter eb->db, abspath, pool)); 395251881Speter 396251881Speter if (kind == svn_node_unknown 397251881Speter || status == svn_wc__db_status_not_present 398251881Speter || status == svn_wc__db_status_excluded 399251881Speter || status == svn_wc__db_status_server_excluded) 400251881Speter return SVN_NO_ERROR; 401251881Speter } 402251881Speter 403251881Speter return eb->wrapped_editor->delete_entry(path, base_revision, 404251881Speter pb->wrapped_baton, pool); 405251881Speter} 406251881Speter 407251881Speter/* An svn_delta_editor_t function. */ 408251881Speterstatic svn_error_t * 409251881Speteradd_directory(const char *path, 410251881Speter void *parent_baton, 411251881Speter const char *copyfrom_path, 412251881Speter svn_revnum_t copyfrom_revision, 413251881Speter apr_pool_t *pool, 414251881Speter void **child_baton) 415251881Speter{ 416251881Speter struct dir_baton *pb = parent_baton; 417251881Speter struct edit_baton *eb = pb->edit_baton; 418251881Speter struct dir_baton *b = NULL; 419251881Speter 420251881Speter SVN_ERR(make_dir_baton(&b, path, eb, pb, TRUE, pool)); 421251881Speter *child_baton = b; 422251881Speter 423251881Speter if (b->ambiently_excluded) 424251881Speter return SVN_NO_ERROR; 425251881Speter 426251881Speter /* It's not excluded, so what should we treat the ambient depth as 427251881Speter being? */ 428251881Speter if (strcmp(eb->target, path) == 0) 429251881Speter { 430251881Speter /* The target of the edit is being added, so make it 431251881Speter infinity. */ 432251881Speter b->ambient_depth = svn_depth_infinity; 433251881Speter } 434251881Speter else if (pb->ambient_depth == svn_depth_immediates) 435251881Speter { 436251881Speter b->ambient_depth = svn_depth_empty; 437251881Speter } 438251881Speter else 439251881Speter { 440251881Speter /* There may be a requested depth < svn_depth_infinity, but 441251881Speter that's okay, libsvn_delta/depth_filter_editor.c will filter 442251881Speter further calls out for us anyway, and the update_editor will 443251881Speter do the right thing when it creates the directory. */ 444251881Speter b->ambient_depth = svn_depth_infinity; 445251881Speter } 446251881Speter 447251881Speter return eb->wrapped_editor->add_directory(path, pb->wrapped_baton, 448251881Speter copyfrom_path, 449251881Speter copyfrom_revision, 450251881Speter pool, &b->wrapped_baton); 451251881Speter} 452251881Speter 453251881Speter/* An svn_delta_editor_t function. */ 454251881Speterstatic svn_error_t * 455251881Speteropen_directory(const char *path, 456251881Speter void *parent_baton, 457251881Speter svn_revnum_t base_revision, 458251881Speter apr_pool_t *pool, 459251881Speter void **child_baton) 460251881Speter{ 461251881Speter struct dir_baton *pb = parent_baton; 462251881Speter struct edit_baton *eb = pb->edit_baton; 463251881Speter struct dir_baton *b; 464251881Speter const char *local_abspath; 465251881Speter svn_node_kind_t kind; 466251881Speter svn_wc__db_status_t status; 467251881Speter svn_depth_t depth; 468251881Speter 469251881Speter SVN_ERR(make_dir_baton(&b, path, eb, pb, FALSE, pool)); 470251881Speter *child_baton = b; 471251881Speter 472251881Speter if (b->ambiently_excluded) 473251881Speter return SVN_NO_ERROR; 474251881Speter 475251881Speter SVN_ERR(eb->wrapped_editor->open_directory(path, pb->wrapped_baton, 476251881Speter base_revision, pool, 477251881Speter &b->wrapped_baton)); 478251881Speter /* Note that for the update editor, the open_directory above will 479251881Speter flush the logs of pb's directory, which might be important for 480251881Speter this svn_wc_entry call. */ 481251881Speter 482251881Speter local_abspath = svn_dirent_join(eb->anchor_abspath, path, pool); 483251881Speter 484251881Speter SVN_ERR(ambient_read_info(&status, &kind, &depth, 485251881Speter eb->db, local_abspath, pool)); 486251881Speter 487251881Speter if (kind != svn_node_unknown 488251881Speter && status != svn_wc__db_status_not_present 489251881Speter && status != svn_wc__db_status_excluded 490251881Speter && status != svn_wc__db_status_server_excluded) 491251881Speter { 492251881Speter b->ambient_depth = depth; 493251881Speter } 494251881Speter 495251881Speter return SVN_NO_ERROR; 496251881Speter} 497251881Speter 498251881Speter/* An svn_delta_editor_t function. */ 499251881Speterstatic svn_error_t * 500251881Speteradd_file(const char *path, 501251881Speter void *parent_baton, 502251881Speter const char *copyfrom_path, 503251881Speter svn_revnum_t copyfrom_revision, 504251881Speter apr_pool_t *pool, 505251881Speter void **child_baton) 506251881Speter{ 507251881Speter struct dir_baton *pb = parent_baton; 508251881Speter struct edit_baton *eb = pb->edit_baton; 509251881Speter struct file_baton *b = NULL; 510251881Speter 511251881Speter SVN_ERR(make_file_baton(&b, pb, path, TRUE, pool)); 512251881Speter *child_baton = b; 513251881Speter 514251881Speter if (b->ambiently_excluded) 515251881Speter return SVN_NO_ERROR; 516251881Speter 517251881Speter return eb->wrapped_editor->add_file(path, pb->wrapped_baton, 518251881Speter copyfrom_path, copyfrom_revision, 519251881Speter pool, &b->wrapped_baton); 520251881Speter} 521251881Speter 522251881Speter/* An svn_delta_editor_t function. */ 523251881Speterstatic svn_error_t * 524251881Speteropen_file(const char *path, 525251881Speter void *parent_baton, 526251881Speter svn_revnum_t base_revision, 527251881Speter apr_pool_t *pool, 528251881Speter void **child_baton) 529251881Speter{ 530251881Speter struct dir_baton *pb = parent_baton; 531251881Speter struct edit_baton *eb = pb->edit_baton; 532251881Speter struct file_baton *b; 533251881Speter 534251881Speter SVN_ERR(make_file_baton(&b, pb, path, FALSE, pool)); 535251881Speter *child_baton = b; 536251881Speter if (b->ambiently_excluded) 537251881Speter return SVN_NO_ERROR; 538251881Speter 539251881Speter return eb->wrapped_editor->open_file(path, pb->wrapped_baton, 540251881Speter base_revision, pool, 541251881Speter &b->wrapped_baton); 542251881Speter} 543251881Speter 544251881Speter/* An svn_delta_editor_t function. */ 545251881Speterstatic svn_error_t * 546251881Speterapply_textdelta(void *file_baton, 547251881Speter const char *base_checksum, 548251881Speter apr_pool_t *pool, 549251881Speter svn_txdelta_window_handler_t *handler, 550251881Speter void **handler_baton) 551251881Speter{ 552251881Speter struct file_baton *fb = file_baton; 553251881Speter struct edit_baton *eb = fb->edit_baton; 554251881Speter 555251881Speter /* For filtered files, we just consume the textdelta. */ 556251881Speter if (fb->ambiently_excluded) 557251881Speter { 558251881Speter *handler = svn_delta_noop_window_handler; 559251881Speter *handler_baton = NULL; 560251881Speter return SVN_NO_ERROR; 561251881Speter } 562251881Speter 563251881Speter return eb->wrapped_editor->apply_textdelta(fb->wrapped_baton, 564251881Speter base_checksum, pool, 565251881Speter handler, handler_baton); 566251881Speter} 567251881Speter 568251881Speter/* An svn_delta_editor_t function. */ 569251881Speterstatic svn_error_t * 570251881Speterclose_file(void *file_baton, 571251881Speter const char *text_checksum, 572251881Speter apr_pool_t *pool) 573251881Speter{ 574251881Speter struct file_baton *fb = file_baton; 575251881Speter struct edit_baton *eb = fb->edit_baton; 576251881Speter 577251881Speter if (fb->ambiently_excluded) 578251881Speter return SVN_NO_ERROR; 579251881Speter 580251881Speter return eb->wrapped_editor->close_file(fb->wrapped_baton, 581251881Speter text_checksum, pool); 582251881Speter} 583251881Speter 584251881Speter/* An svn_delta_editor_t function. */ 585251881Speterstatic svn_error_t * 586251881Speterabsent_file(const char *path, 587251881Speter void *parent_baton, 588251881Speter apr_pool_t *pool) 589251881Speter{ 590251881Speter struct dir_baton *pb = parent_baton; 591251881Speter struct edit_baton *eb = pb->edit_baton; 592251881Speter 593251881Speter if (pb->ambiently_excluded) 594251881Speter return SVN_NO_ERROR; 595251881Speter 596251881Speter return eb->wrapped_editor->absent_file(path, pb->wrapped_baton, pool); 597251881Speter} 598251881Speter 599251881Speter/* An svn_delta_editor_t function. */ 600251881Speterstatic svn_error_t * 601251881Speterclose_directory(void *dir_baton, 602251881Speter apr_pool_t *pool) 603251881Speter{ 604251881Speter struct dir_baton *db = dir_baton; 605251881Speter struct edit_baton *eb = db->edit_baton; 606251881Speter 607251881Speter if (db->ambiently_excluded) 608251881Speter return SVN_NO_ERROR; 609251881Speter 610251881Speter return eb->wrapped_editor->close_directory(db->wrapped_baton, pool); 611251881Speter} 612251881Speter 613251881Speter/* An svn_delta_editor_t function. */ 614251881Speterstatic svn_error_t * 615251881Speterabsent_directory(const char *path, 616251881Speter void *parent_baton, 617251881Speter apr_pool_t *pool) 618251881Speter{ 619251881Speter struct dir_baton *pb = parent_baton; 620251881Speter struct edit_baton *eb = pb->edit_baton; 621251881Speter 622251881Speter /* Don't report absent items in filtered directories. */ 623251881Speter if (pb->ambiently_excluded) 624251881Speter return SVN_NO_ERROR; 625251881Speter 626251881Speter return eb->wrapped_editor->absent_directory(path, pb->wrapped_baton, pool); 627251881Speter} 628251881Speter 629251881Speter/* An svn_delta_editor_t function. */ 630251881Speterstatic svn_error_t * 631251881Speterchange_file_prop(void *file_baton, 632251881Speter const char *name, 633251881Speter const svn_string_t *value, 634251881Speter apr_pool_t *pool) 635251881Speter{ 636251881Speter struct file_baton *fb = file_baton; 637251881Speter struct edit_baton *eb = fb->edit_baton; 638251881Speter 639251881Speter if (fb->ambiently_excluded) 640251881Speter return SVN_NO_ERROR; 641251881Speter 642251881Speter return eb->wrapped_editor->change_file_prop(fb->wrapped_baton, 643251881Speter name, value, pool); 644251881Speter} 645251881Speter 646251881Speter/* An svn_delta_editor_t function. */ 647251881Speterstatic svn_error_t * 648251881Speterchange_dir_prop(void *dir_baton, 649251881Speter const char *name, 650251881Speter const svn_string_t *value, 651251881Speter apr_pool_t *pool) 652251881Speter{ 653251881Speter struct dir_baton *db = dir_baton; 654251881Speter struct edit_baton *eb = db->edit_baton; 655251881Speter 656251881Speter if (db->ambiently_excluded) 657251881Speter return SVN_NO_ERROR; 658251881Speter 659251881Speter return eb->wrapped_editor->change_dir_prop(db->wrapped_baton, 660251881Speter name, value, pool); 661251881Speter} 662251881Speter 663251881Speter/* An svn_delta_editor_t function. */ 664251881Speterstatic svn_error_t * 665251881Speterclose_edit(void *edit_baton, 666251881Speter apr_pool_t *pool) 667251881Speter{ 668251881Speter struct edit_baton *eb = edit_baton; 669251881Speter return eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool); 670251881Speter} 671251881Speter 672251881Spetersvn_error_t * 673251881Spetersvn_wc__ambient_depth_filter_editor(const svn_delta_editor_t **editor, 674251881Speter void **edit_baton, 675251881Speter svn_wc__db_t *db, 676251881Speter const char *anchor_abspath, 677251881Speter const char *target, 678251881Speter const svn_delta_editor_t *wrapped_editor, 679251881Speter void *wrapped_edit_baton, 680251881Speter apr_pool_t *result_pool) 681251881Speter{ 682251881Speter svn_delta_editor_t *depth_filter_editor; 683251881Speter struct edit_baton *eb; 684251881Speter 685251881Speter SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath)); 686251881Speter 687251881Speter depth_filter_editor = svn_delta_default_editor(result_pool); 688251881Speter depth_filter_editor->set_target_revision = set_target_revision; 689251881Speter depth_filter_editor->open_root = open_root; 690251881Speter depth_filter_editor->delete_entry = delete_entry; 691251881Speter depth_filter_editor->add_directory = add_directory; 692251881Speter depth_filter_editor->open_directory = open_directory; 693251881Speter depth_filter_editor->change_dir_prop = change_dir_prop; 694251881Speter depth_filter_editor->close_directory = close_directory; 695251881Speter depth_filter_editor->absent_directory = absent_directory; 696251881Speter depth_filter_editor->add_file = add_file; 697251881Speter depth_filter_editor->open_file = open_file; 698251881Speter depth_filter_editor->apply_textdelta = apply_textdelta; 699251881Speter depth_filter_editor->change_file_prop = change_file_prop; 700251881Speter depth_filter_editor->close_file = close_file; 701251881Speter depth_filter_editor->absent_file = absent_file; 702251881Speter depth_filter_editor->close_edit = close_edit; 703251881Speter 704251881Speter eb = apr_pcalloc(result_pool, sizeof(*eb)); 705251881Speter eb->wrapped_editor = wrapped_editor; 706251881Speter eb->wrapped_edit_baton = wrapped_edit_baton; 707251881Speter eb->db = db; 708251881Speter eb->anchor_abspath = anchor_abspath; 709251881Speter eb->target = target; 710251881Speter 711251881Speter *editor = depth_filter_editor; 712251881Speter *edit_baton = eb; 713251881Speter 714251881Speter return SVN_NO_ERROR; 715251881Speter} 716