You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Karl Fogel <kf...@red-bean.com> on 2008/11/08 03:26:08 UTC

Re: svn commit: r34108 - in trunk: . subversion/include subversion/include/private subversion/libsvn_auth_kwallet subversion/libsvn_client subversion/libsvn_repos subversion/libsvn_subr subversion/libsvn_wc subversion/svn subversion/tests/cmdline subversion/tests/libsvn_subr tools/buildbot/slaves/win32-xp-VS2005 tools/server-side www

pburba@tigris.org writes:
> Log:
> Merge the issue-2843 branch back to trunk.
>
> I wasn't able to use reintegrate, see 
> http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=145078.  So 
> this was done the old-fashioned way, with a 2-URL merge:
> http://svn.collab.net/repos/svn/trunk@34105
> http://svn.collab.net/repos/svn/branches/issue-2843-dev@34105.
>
> Note: This merge added mergeinfo on the subversion directory.  This
> mergeinfo originated in r31940 on the issue-2843 branch, but there is no
> obvious reason why it was there.  r31940 was a merge of r31359-31939 from
> trunk, but there is no mergeinfo diff between those revs, so where this came
> from is a complete mystery.  In that light I removed this mergeinfo prior to
> the commit.

Thanks, Paul.  I'm pretty sure if I'd tried to get there on my own, I
would have done something even more hackish.



> Added:
>    trunk/subversion/libsvn_wc/crop.c
>       - copied unchanged from r34105, branches/issue-2843-dev/subversion/libsvn_wc/crop.c
> Modified:
>    trunk/   (props changed)
>    trunk/build.conf   (props changed)
>    trunk/subversion/include/   (props changed)
>    trunk/subversion/include/private/svn_auth_private.h   (props changed)
>    trunk/subversion/include/private/svn_cache.h   (props changed)
>    trunk/subversion/include/svn_wc.h
>    trunk/subversion/libsvn_auth_kwallet/kwallet.cpp   (props changed)
>    trunk/subversion/libsvn_client/commit_util.c
>    trunk/subversion/libsvn_client/copy.c
>    trunk/subversion/libsvn_client/diff.c
>    trunk/subversion/libsvn_client/merge.c
>    trunk/subversion/libsvn_client/ra.c
>    trunk/subversion/libsvn_client/status.c
>    trunk/subversion/libsvn_client/switch.c
>    trunk/subversion/libsvn_client/update.c
>    trunk/subversion/libsvn_repos/reporter.c
>    trunk/subversion/libsvn_subr/   (props changed)
>    trunk/subversion/libsvn_wc/README
>    trunk/subversion/libsvn_wc/adm_crawler.c
>    trunk/subversion/libsvn_wc/adm_ops.c
>    trunk/subversion/libsvn_wc/ambient_depth_filter_editor.c
>    trunk/subversion/libsvn_wc/copy.c
>    trunk/subversion/libsvn_wc/entries.c
>    trunk/subversion/libsvn_wc/lock.c
>    trunk/subversion/libsvn_wc/log.c
>    trunk/subversion/libsvn_wc/props.c
>    trunk/subversion/libsvn_wc/relocate.c
>    trunk/subversion/libsvn_wc/update_editor.c
>    trunk/subversion/svn/main.c
>    trunk/subversion/tests/cmdline/depth_tests.py
>    trunk/subversion/tests/cmdline/tree_conflict_tests.txt   (props changed)
>    trunk/subversion/tests/libsvn_subr/   (props changed)
>    trunk/tools/buildbot/slaves/win32-xp-VS2005/   (props changed)
>    trunk/tools/server-side/svn_server_log_parse.py   (props changed)
>    trunk/tools/server-side/test_svn_server_log_parse.py   (props changed)
>    trunk/www/development.html   (props changed)
>    trunk/www/issue-tracker.html   (props changed)
>    trunk/www/tasks.html   (props changed)
>
> Merged:
>    /branches/issue-2843-dev:r31358-34105
>
> Modified: trunk/subversion/include/svn_wc.h
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/include/svn_wc.h?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/include/svn_wc.h	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/include/svn_wc.h	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -2070,11 +2070,12 @@ typedef struct svn_wc_entry_t
>  #define SVN_WC_ENTRY_THIS_DIR  ""
>  
>  
> -/** Set @a *entry to an entry for @a path, allocated in the access baton
> - * pool.  If @a show_hidden is TRUE, return the entry even if it's in
> - * 'deleted' or 'absent' state.  If @a path is not under revision
> - * control, or if entry is hidden, not scheduled for re-addition,
> - * and @a show_hidden is @c FALSE, then set @a *entry to @c NULL.
> +/** Set @a *entry to an entry for @a path, allocated in the access baton pool.
> + * If @a show_hidden is TRUE, return the entry even if it's in 'excluded',
> + * 'deleted' or 'absent' state. Excluded entries are those with their depth
> + * set to @c svn_depth_exclude. If @a path is not under revision control, or
> + * if entry is hidden, not scheduled for re-addition, and @a show_hidden is @c
> + * FALSE, then set @a *entry to @c NULL.
>   *
>   * @a *entry should not be modified, since doing so modifies the entries
>   * cache in @a adm_access without changing the entries file on disk.
> @@ -2109,9 +2110,10 @@ svn_wc_entry(const svn_wc_entry_t **entr
>   * baton (that's how the entries caching works).  @a pool is used for
>   * transient allocations.
>   *
> - * Entries that are in a 'deleted' or 'absent' state (and not
> + * Entries that are in a 'excluded', 'deleted' or 'absent' state (and not
>   * scheduled for re-addition) are not returned in the hash, unless
> - * @a show_hidden is TRUE.
> + * @a show_hidden is TRUE. Excluded entries are those with their depth set to
> + * @c svn_depth_exclude.
>   *
>   * @par Important:
>   * The @a entries hash is the entries cache in @a adm_access
> @@ -2258,9 +2260,10 @@ typedef struct svn_wc_entry_callbacks_t
>   * If @a cancel_func is non-NULL, call it with @a cancel_baton to determine
>   * if the client has cancelled the operation.
>   *
> - * Like our other entries interfaces, entries that are in a 'deleted'
> - * or 'absent' state (and not scheduled for re-addition) are not
> - * discovered, unless @a show_hidden is TRUE.
> + * Like our other entries interfaces, entries that are in a 'excluded',
> + * 'deleted' or 'absent' state (and not scheduled for re-addition) are not
> + * discovered, unless @a show_hidden is TRUE. Excluded entries are those with
> + * their depth set to @c svn_depth_exclude.
>   *
>   * When a new directory is entered, @c SVN_WC_ENTRY_THIS_DIR will always
>   * be returned first.
> @@ -3618,6 +3621,23 @@ svn_wc_process_committed(const char *pat
>   * course.  If @a depth is @c svn_depth_unknown, then just use
>   * @c svn_depth_infinity, which in practice means depth of @a path.
>   *
> + * Iff @a honor_depth_exclude is TRUE, the crawler will report paths
> + * whose ambient depth is @c svn_depth_exclude as being excluded, and
> + * thus prevent the server from pushing update data for those paths;
> + * therefore, don't set this flag if you wish to pull in excluded paths.
> + * Note that @c svn_depth_exclude on the target @a path is never
> + * honored, even if @a honor_depth_exclude is TRUE, because we need to
> + * be able to explicitly pull in a target.  For example, if this is
> + * the working copy...
> + *
> + *    svn co greek_tree_repos wc_dir
> + *    svn up --set-depth exclude wc_dir/A/B/E  # now A/B/E is excluded
> + *
> + * ...then 'svn up wc_dir/A/B' would report E as excluded (assuming
> + * @a honor_depth_exclude is TRUE), but 'svn up wc_dir/A/B/E' would
> + * not, because the latter is trying to explicitly pull in E.  In
> + * general, we never report the update target as excluded.
> + *
>   * Iff @a depth_compatibility_trick is TRUE, then set the @c start_empty
>   * flag on @a reporter->set_path() and @a reporter->link_path() calls
>   * as necessary to trick a pre-1.5 (i.e., depth-unaware) server into
> @@ -3636,7 +3656,28 @@ svn_wc_process_committed(const char *pat
>   * state in it.  (Caller should obtain @a traversal_info from
>   * svn_wc_init_traversal_info().)
>   *
> - * @since New in 1.5.
> + * @since New in 1.6.
> + */
> +svn_error_t *
> +svn_wc_crawl_revisions4(const char *path,
> +                        svn_wc_adm_access_t *adm_access,
> +                        const svn_ra_reporter3_t *reporter,
> +                        void *report_baton,
> +                        svn_boolean_t restore_files,
> +                        svn_depth_t depth,
> +                        svn_boolean_t honor_depth_exclude,
> +                        svn_boolean_t depth_compatibility_trick,
> +                        svn_boolean_t use_commit_times,
> +                        svn_wc_notify_func2_t notify_func,
> +                        void *notify_baton,
> +                        svn_wc_traversal_info_t *traversal_info,
> +                        apr_pool_t *pool);
> +
> +/**
> + * Similar to svn_wc_crawl_revisions4, but with @a honor_depth_exclude always
> + * set to false.
> + *
> + * @deprecated Provided for compatibility with the 1.5 API.
>   */
>  svn_error_t *
>  svn_wc_crawl_revisions3(const char *path,
> @@ -5262,6 +5303,46 @@ svn_wc_set_changelist(const char *path,
>                        void *notify_baton,
>                        apr_pool_t *pool);
>  
> +/** Crop @a target according to @a depth. 
> + *
> + * Remove any item that exceeds the boundary of @a depth (relative to
> + * @a target) from revision control.  Leave modified items behind
> + * (unversioned), while removing unmodified ones completely.
> + *
> + * If @a target starts out with a shallower depth than @a depth, do not
> + * upgrade it to @a depth (that would not be cropping); however, do
> + * check children and crop them appropriately according to @a depth.
> + *
> + * Returns immediately with no error if @a target is not a directory,
> + * or if @a depth is not restrictive (e.g., @c svn_depth_infinity).
> + *
> + * @a anchor is an access baton, with a tree lock, for the local path to the
> + * working copy which will be used as the root of this operation.  If
> + * @a target is not empty, it represents an entry in the @a anchor path;
> + * otherwise, the @a anchor path is the target.  @a target may not be
> + * @c NULL.
> + *
> + * If @a cancel_func is not @c NULL, call it with @a cancel_baton at
> + * various points to determine if the client has cancelled the operation.
> + *
> + * If @a notify_func is not @c NULL, call it with @a notify_baton to
> + * report changes as they are made.
> + *
> + * @note: svn_depth_exclude currently does nothing; passing it results
> + * in immediate success with no side effects.
> + *
> + * @since New in 1.6
> + */
> +svn_error_t *
> +svn_wc_crop_tree(svn_wc_adm_access_t *anchor,
> +                 const char *target,
> +                 svn_depth_t depth,
> +                 svn_wc_notify_func2_t notify_func,
> +                 void *notify_baton,
> +                 svn_cancel_func_t cancel_func,
> +                 void *cancel_baton,
> +                 apr_pool_t *pool);
> +
>  /** @} */
>  
>  /** Set @a *tree_conflict to a newly allocated @c
>
> Modified: trunk/subversion/libsvn_client/commit_util.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/commit_util.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/commit_util.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/commit_util.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -561,6 +561,11 @@ harvest_committables(apr_hash_t *committ
>              continue;
>  
>            this_entry = val;
> +
> +          /* Skip the excluded item. */
> +          if (this_entry->depth == svn_depth_exclude)
> +            continue;
> +
>            name_uri = svn_path_uri_encode(name, loop_pool);
>  
>            full_path = svn_path_join(path, name, loop_pool);
> @@ -1271,7 +1276,11 @@ do_item_commit(void **dir_baton,
>              }
>          }
>  
> -      SVN_ERR(svn_wc_entry(&tmp_entry, item->path, adm_access, TRUE, pool));
> +      /* Ensured by harvest_commitables(), item->path will never be an
> +         excluded path. However, will it be deleted/absent items?  I think
> +         committing an modification on a deleted/absent item does not make
> +         sense. So it's probably safe to turn off the show_hidden flag here.*/
> +      SVN_ERR(svn_wc_entry(&tmp_entry, item->path, adm_access, FALSE, pool));
>  
>        /* When committing a directory that no longer exists in the
>           repository, a "not found" error does not occur immediately
>
> Modified: trunk/subversion/libsvn_client/copy.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/copy.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/copy.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/copy.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -1615,13 +1615,28 @@ repos_to_wc_copy(const apr_array_header_
>  
>        svn_pool_clear(iterpool);
>  
> -      SVN_ERR(svn_wc_entry(&ent, pair->dst, adm_access, FALSE, iterpool));
> -      if (ent && (ent->kind != svn_node_dir) &&
> -          (ent->schedule != svn_wc_schedule_delete))
> -        return svn_error_createf
> -          (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
> -           _("Entry for '%s' exists (though the working file is missing)"),
> -           svn_path_local_style(pair->dst, pool));
> +      SVN_ERR(svn_wc_entry(&ent, pair->dst, adm_access, TRUE, iterpool));
> +      if (ent)
> +        {
> +          /* TODO(#2843): Rework the error report. Maybe we can simplify the
> +             condition. Currently, the first is about hidden items and the
> +             second is for missing items. */
> +          if (ent->depth == svn_depth_exclude
> +              || ent->absent)
> +            {
> +              return svn_error_createf
> +                (SVN_ERR_ENTRY_EXISTS, 
> +                 NULL, _("'%s' is already under version control"),
> +                 svn_path_local_style(pair->dst, pool)); 
> +            }
> +          else if ((ent->kind != svn_node_dir) &&
> +                   (ent->schedule != svn_wc_schedule_delete) 
> +                   && ! ent->deleted)
> +            return svn_error_createf
> +              (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
> +               _("Entry for '%s' exists (though the working file is missing)"),
> +               svn_path_local_style(pair->dst, pool));
> +        }
>      }
>  
>    /* Decide whether the two repositories are the same or not. */
>
> Modified: trunk/subversion/libsvn_client/diff.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/diff.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/diff.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/diff.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -1352,9 +1352,9 @@ diff_repos_wc(const char *path1,
>  
>    /* Create a txn mirror of path2;  the diff editor will print
>       diffs in reverse.  :-)  */
> -  SVN_ERR(svn_wc_crawl_revisions3(path2, dir_access,
> +  SVN_ERR(svn_wc_crawl_revisions4(path2, dir_access,
>                                    reporter, report_baton,
> -                                  FALSE, depth, (! server_supports_depth),
> +                                  FALSE, depth, TRUE, (! server_supports_depth),
>                                    FALSE, NULL, NULL, /* notification is N/A */
>                                    NULL, pool));
>  
>
> Modified: trunk/subversion/libsvn_client/merge.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/merge.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/merge.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/merge.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -155,7 +155,7 @@ check_scheme_match(svn_wc_adm_access_t *
>    const svn_wc_entry_t *ent;
>    const char *idx1, *idx2;
>  
> -  SVN_ERR(svn_wc_entry(&ent, path, adm_access, TRUE, pool));
> +  SVN_ERR(svn_wc_entry(&ent, path, adm_access, FALSE, pool));
>  
>    idx1 = strchr(url, ':');
>    idx2 = strchr(ent->url, ':');
> @@ -3917,6 +3917,8 @@ get_mergeinfo_walk_cb(const char *path,
>      !svn_path_compare_paths(path, wb->merge_target_path);
>    const char *parent_path = svn_path_dirname(path, pool);
>  
> +  /* TODO(#2843) How to deal with a excluded item on merge? */
> +
>    /* We're going to receive dirents twice;  we want to ignore the
>       first one (where it's a child of a parent dir), and only use
>       the second one (where we're looking at THIS_DIR).  The exception
>
> Modified: trunk/subversion/libsvn_client/ra.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/ra.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/ra.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/ra.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -416,6 +416,9 @@ svn_client_uuid_from_path(const char **u
>      }
>    else
>      {
> +      /* Excluded path will fall into this code branch, since the missed
> +         fields in the entry for excluded path is not filled. But it is just
> +         ok. */
>        return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
>                                 _("'%s' has no URL"),
>                                 svn_path_local_style(path, pool));
>
> Modified: trunk/subversion/libsvn_client/status.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/status.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/status.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/status.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -358,9 +358,9 @@ svn_client_status4(svn_revnum_t *result_
>               within PATH.  When we call reporter->finish_report,
>               EDITOR will be driven to describe differences between our
>               working copy and HEAD. */
> -          SVN_ERR(svn_wc_crawl_revisions3(path, target_access,
> +          SVN_ERR(svn_wc_crawl_revisions4(path, target_access,
>                                            &lock_fetch_reporter, &rb, FALSE,
> -                                          depth, (! server_supports_depth),
> +                                          depth, TRUE, (! server_supports_depth),
>                                            FALSE, NULL, NULL, NULL, pool));
>          }
>      }
>
> Modified: trunk/subversion/libsvn_client/switch.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/switch.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/switch.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/switch.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -92,6 +92,11 @@ svn_client__switch_internal(svn_revnum_t
>    if (depth == svn_depth_unknown)
>      depth_is_sticky = FALSE;
>  
> +  /* Do not support the situation of both exclude and switch a target. */
> +  if (depth_is_sticky && depth == svn_depth_exclude)
> +    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
> +                             _("Can not both exclude and switch a path"));
> +
>    /* Get the external diff3, if any. */
>    svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
>                   SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
> @@ -166,6 +171,15 @@ svn_client__switch_internal(svn_revnum_t
>           "is not the same repository as\n"
>           "'%s'"), URL, source_root);
>  
> +  /* We may need to crop the tree if the depth is sticky */
> +  if (depth_is_sticky && depth < svn_depth_infinity)
> +    {
> +      SVN_ERR(svn_wc_crop_tree(adm_access, target, depth, 
> +                               ctx->notify_func2, ctx->notify_baton2,
> +                               ctx->cancel_func, ctx->cancel_baton,
> +                               pool));
> +    }
> +
>    SVN_ERR(svn_ra_reparent(ra_session, URL, pool));
>  
>    /* Fetch the switch (update) editor.  If REVISION is invalid, that's
> @@ -196,8 +210,9 @@ svn_client__switch_internal(svn_revnum_t
>       We pass NULL for traversal_info because this is a switch, not an
>       update, and therefore we don't want to handle any externals
>       except the ones directly affected by the switch. */
> -  err = svn_wc_crawl_revisions3(path, dir_access, reporter, report_baton,
> -                                TRUE, depth, (! server_supports_depth),
> +  err = svn_wc_crawl_revisions4(path, dir_access, reporter, report_baton,
> +                                TRUE, depth, (! depth_is_sticky),
> +                                (! server_supports_depth),
>                                  use_commit_times,
>                                  ctx->notify_func2, ctx->notify_baton2,
>                                  NULL, /* no traversal info */
>
> Modified: trunk/subversion/libsvn_client/update.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_client/update.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_client/update.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_client/update.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -127,7 +127,11 @@ svn_client__update_internal(svn_revnum_t
>       ### lock the entire tree when we don't actually need to, that's a
>       ### performance hit, but (except for access contention) it is not
>       ### a correctness problem. */
> -  levels_to_lock = SVN_WC__LEVELS_TO_LOCK_FROM_DEPTH(depth);
> +
> +  /* We may have to crop the subtree if the depth is sticky, so lock the
> +     entire tree in such a situation*/
> +  levels_to_lock = depth_is_sticky 
> +    ? -1 : SVN_WC__LEVELS_TO_LOCK_FROM_DEPTH(depth);
>  
>    /* Sanity check.  Without this, the update is meaningless. */
>    SVN_ERR_ASSERT(path);
> @@ -151,6 +155,21 @@ svn_client__update_internal(svn_revnum_t
>                               _("Entry '%s' has no URL"),
>                               svn_path_local_style(anchor, pool));
>  
> +  /* We may need to crop the tree if the depth is sticky */
> +  if (depth_is_sticky && depth < svn_depth_infinity)
> +    {
> +      SVN_ERR(svn_wc_crop_tree(adm_access, target, depth, 
> +                               ctx->notify_func2, ctx->notify_baton2,
> +                               ctx->cancel_func, ctx->cancel_baton,
> +                               pool));
> +      /* If we are asked to exclude a target, we can just stop now. */
> +      if (depth == svn_depth_exclude)
> +        {
> +          SVN_ERR(svn_wc_adm_close2(adm_access, pool));
> +          return SVN_NO_ERROR;
> +        }
> +    }
> +
>    /* Get revnum set to something meaningful, so we can fetch the
>       update editor. */
>    if (revision->kind == svn_opt_revision_number)
> @@ -232,8 +251,9 @@ svn_client__update_internal(svn_revnum_t
>    /* Drive the reporter structure, describing the revisions within
>       PATH.  When we call reporter->finish_report, the
>       update_editor will be driven by svn_repos_dir_delta2. */
> -  err = svn_wc_crawl_revisions3(path, dir_access, reporter, report_baton,
> -                                TRUE, depth, (! server_supports_depth),
> +  err = svn_wc_crawl_revisions4(path, dir_access, reporter, report_baton,
> +                                TRUE, depth, (! depth_is_sticky), 
> +                                (! server_supports_depth),
>                                  use_commit_times,
>                                  ctx->notify_func2, ctx->notify_baton2,
>                                  traversal_info, pool);
>
> Modified: trunk/subversion/libsvn_repos/reporter.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_repos/reporter.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_repos/reporter.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_repos/reporter.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -1017,7 +1017,10 @@ delta_dirs(report_baton_t *b, svn_revnum
>  
>            /* Don't revisit this name in the target or source entries. */
>            apr_hash_set(t_entries, name, APR_HASH_KEY_STRING, NULL);
> -          if (s_entries)
> +          if (s_entries
> +              /* Keep the entry for later process if it is reported as
> +                 excluded and got deleted in repos. */ 
> +              && (! info || info->depth != svn_depth_exclude || t_entry))
>              apr_hash_set(s_entries, name, APR_HASH_KEY_STRING, NULL);
>  
>            /* pathinfo entries live in their own subpools due to lookahead,
>
> Modified: trunk/subversion/libsvn_wc/README
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/README?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/README	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/README	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -503,6 +503,13 @@ depth:
>     entries and pulls new entries with depth infinity as well.
>     Default is infinite (`').
>  
> +   Apart from above normal values, there is still a special `exclude',
> +   which means the directory is excluded from wc even if the depth of
> +   parent directory is infinity or immediates. The directory in
> +   question will not physically exist on the disk. In other words, we
> +   can only store the `exclude' value in the corresponding entry of
> +   the entries file in parent directory. 
> +
>  tree-conflicts:
>     A list of details of the tree conflicts that children are currently
>     suffering. This is only allowed on the this_dir entry.
> @@ -519,8 +526,9 @@ file-external:
>  
>  The only fields allowed in an entry for a directory (other than the
>  this_dir entry) are name, absent, deleted, schedule, copied,
> -copyfrom-url, copyfrom-rev and kind.  The other fields are only stored
> -in the this_dir entry for the directory in question.
> +copyfrom-url, copyfrom-rev, kind and depth (only when the value says
> +exclude).  The other fields are only stored in the this_dir entry for
> +the directory in question.
>  
>  
>  XML-based entries format
>
> Modified: trunk/subversion/libsvn_wc/adm_crawler.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/adm_crawler.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/adm_crawler.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/adm_crawler.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -179,6 +179,7 @@ report_revisions_and_depths(svn_wc_adm_a
>                              void *notify_baton,
>                              svn_boolean_t restore_files,
>                              svn_depth_t depth,
> +                            svn_boolean_t honor_depth_exclude,
>                              svn_boolean_t depth_compatibility_trick,
>                              svn_boolean_t report_everything,
>                              svn_boolean_t use_commit_times,
> @@ -272,6 +273,39 @@ report_revisions_and_depths(svn_wc_adm_a
>            continue;
>          }
>  
> +      if (current_entry->depth == svn_depth_exclude)
> +        {
> +          if (honor_depth_exclude)
> +            {
> +              /* Report the excluded path, no matter whether report_everything
> +                 flag is set.  Because the report_everything flag indicates
> +                 that the server will treate the wc as empty and thus push
> +                 full content of the files/subdirs. But we want to prevent the
> +                 server from pushing the full content of this_path at us. */
> +
> +              /* The server does not support link_path report on excluded
> +                 path. We explicitly prohibit this situation in
> +                 svn_wc_crop_tree(). */
> +              SVN_ERR(reporter->set_path(report_baton,
> +                                         this_path,
> +                                         dir_rev,
> +                                         svn_depth_exclude,
> +                                         FALSE,
> +                                         NULL,
> +                                         iterpool));
> +            }
> +          else
> +            {
> +              /* We want to pull in the excluded target. So, report it as deleted,
> +                 and server will respond properly. */
> +              if (! report_everything)
> +                SVN_ERR(reporter->delete_path(report_baton, 
> +                                              this_path, iterpool));
> +            }
> +
> +          continue;
> +        }
> +
>        /* Is the entry on disk?  Set a flag if not. */
>        dirent = apr_hash_get(dirents, key, klen);
>        if (! dirent)
> @@ -452,6 +486,7 @@ report_revisions_and_depths(svn_wc_adm_a
>                                                  reporter, report_baton,
>                                                  notify_func, notify_baton,
>                                                  restore_files, depth,
> +                                                honor_depth_exclude,
>                                                  depth_compatibility_trick,
>                                                  start_empty,
>                                                  use_commit_times,
> @@ -472,12 +507,13 @@ report_revisions_and_depths(svn_wc_adm_a
>  
>  
>  svn_error_t *
> -svn_wc_crawl_revisions3(const char *path,
> +svn_wc_crawl_revisions4(const char *path,
>                          svn_wc_adm_access_t *adm_access,
>                          const svn_ra_reporter3_t *reporter,
>                          void *report_baton,
>                          svn_boolean_t restore_files,
>                          svn_depth_t depth,
> +                        svn_boolean_t honor_depth_exclude,
>                          svn_boolean_t depth_compatibility_trick,
>                          svn_boolean_t use_commit_times,
>                          svn_wc_notify_func2_t notify_func,
> @@ -501,6 +537,16 @@ svn_wc_crawl_revisions3(const char *path
>    if ((! entry) || ((entry->schedule == svn_wc_schedule_add)
>                      && (entry->kind == svn_node_dir)))
>      {
> +      /* Don't check the exclude flag for the target.
> +
> +         If we report the target itself as excluded, the server will
> +         send us nothing about the target -- but we want to permit
> +         targets to be explicitly pulled in.  For example, 'svn up A'
> +         should always work, even if its parent is svn_depth_empty or
> +         svn_depth_files, or even if A was explicitly excluded from a
> +         parent at svn_depth_immediates or svn_depth_infinity.
> +         Whatever the case, we want A back now. */
> +
>        /* There aren't any versioned paths to crawl which are known to
>           the repository. */
>        SVN_ERR(svn_wc__entry_versioned(&parent_entry,
> @@ -582,6 +628,7 @@ svn_wc_crawl_revisions3(const char *path
>                                              reporter, report_baton,
>                                              notify_func, notify_baton,
>                                              restore_files, depth,
> +                                            honor_depth_exclude,
>                                              depth_compatibility_trick,
>                                              start_empty,
>                                              use_commit_times,
> @@ -673,6 +720,34 @@ svn_wc_crawl_revisions3(const char *path
>    return err;
>  }
>  
> +svn_error_t *
> +svn_wc_crawl_revisions3(const char *path,
> +                        svn_wc_adm_access_t *adm_access,
> +                        const svn_ra_reporter3_t *reporter,
> +                        void *report_baton,
> +                        svn_boolean_t restore_files,
> +                        svn_depth_t depth,
> +                        svn_boolean_t depth_compatibility_trick,
> +                        svn_boolean_t use_commit_times,
> +                        svn_wc_notify_func2_t notify_func,
> +                        void *notify_baton,
> +                        svn_wc_traversal_info_t *traversal_info,
> +                        apr_pool_t *pool)
> +{
> +  return svn_wc_crawl_revisions4(path,
> +                                 adm_access,
> +                                 reporter, report_baton,
> +                                 restore_files,
> +                                 depth,
> +                                 FALSE,
> +                                 depth_compatibility_trick,
> +                                 use_commit_times,
> +                                 notify_func,
> +                                 notify_baton,
> +                                 traversal_info,
> +                                 pool);
> +}
> +
>  /*** Copying stream ***/
>  
>  /* A copying stream is a bit like the unix tee utility:
>
> Modified: trunk/subversion/libsvn_wc/adm_ops.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/adm_ops.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/adm_ops.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/adm_ops.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -125,10 +125,11 @@ tweak_entries(svn_wc_adm_access_t *dirpa
>            excluded = (apr_hash_get(exclude_paths, child_path,
>                                     APR_HASH_KEY_STRING) != NULL);
>  
> -          /* If a file, or deleted or absent dir, then tweak the entry
> -             but don't recurse. */
> +          /* If a file, or deleted, excluded or absent dir, then tweak the
> +             entry but don't recurse. */
>            if ((current_entry->kind == svn_node_file)
> -              || (current_entry->deleted || current_entry->absent))
> +              || (current_entry->deleted || current_entry->absent
> +                  || current_entry->depth == svn_depth_exclude))
>              {
>                if (! excluded)
>                  SVN_ERR(svn_wc__tweak_entry(entries, name,
> @@ -235,7 +236,9 @@ svn_wc__do_update_cleanup(const char *pa
>      return SVN_NO_ERROR;
>  
>    if (entry->kind == svn_node_file
> -      || (entry->kind == svn_node_dir && (entry->deleted || entry->absent)))
> +      || (entry->kind == svn_node_dir 
> +          && (entry->deleted || entry->absent 
> +              || entry->depth == svn_depth_exclude)))
>      {
>        const char *parent, *base_name;
>        svn_wc_adm_access_t *dir_access;
> @@ -517,6 +520,12 @@ process_committed_internal(int *log_numb
>            if (! strcmp(name, SVN_WC_ENTRY_THIS_DIR))
>              continue;
>  
> +          /* We come to this branch since we have committed a copied tree.
> +             svn_depth_exclude is possible in this situation. So check and
> +             skip */
> +          if (current_entry->depth == svn_depth_exclude)
> +            continue;
> +
>            /* Create child path by telescoping the main path. */
>            this_path = svn_path_join(path, name, subpool);
>  
> @@ -1172,6 +1181,8 @@ svn_wc_delete3(const char *path,
>        /* The deleted state is only available in the entry in parent's
>           entries file */
>        SVN_ERR(svn_wc_adm_retrieve(&parent_access, adm_access, parent, pool));
> +      /* We don't need to check for excluded item, since we won't fall into
> +         this code path in that case. */
>        SVN_ERR(svn_wc_entries_read(&entries, parent_access, TRUE, pool));
>        entry_in_parent = apr_hash_get(entries, base_name, APR_HASH_KEY_STRING);
>        was_deleted = entry_in_parent ? entry_in_parent->deleted : FALSE;
> @@ -1359,12 +1370,15 @@ svn_wc_add3(const char *path,
>       that is slated for deletion from revision control, or has been
>       previously 'deleted', unless, of course, you're specifying an
>       addition with -history-; then it's okay for the object to be
> -     under version control already; it's not really new.  */
> +     under version control already; it's not really new.
> +     Also, if the target is recorded as excluded from wc, it really 
> +     exists in repos. Report error on this situation too. */
>    if (orig_entry)
>      {
> -      if ((! copyfrom_url)
> +      if (((! copyfrom_url)
>            && (orig_entry->schedule != svn_wc_schedule_delete)
>            && (! orig_entry->deleted))
> +          || (orig_entry->depth == svn_depth_exclude))
>          {
>            return svn_error_createf
>              (SVN_ERR_ENTRY_EXISTS, NULL,
> @@ -2019,6 +2033,8 @@ revert_entry(svn_depth_t *depth,
>                                        "directory; please try again from the "
>                                        "parent directory"));
>  
> +          /* We don't need to check for excluded item, since we won't fall
> +             into this code path in that case. */
>            SVN_ERR(svn_wc_entries_read(&entries, parent_access, TRUE, pool));
>            parents_entry = apr_hash_get(entries, basey, APR_HASH_KEY_STRING);
>            if (parents_entry)
> @@ -2104,6 +2120,8 @@ revert_entry(svn_depth_t *depth,
>                svn_wc_entry_t *entry_in_parent;
>                apr_hash_t *entries;
>  
> +              /* The entry to revert will not be an excluded item. Don't
> +                 bother check for it. */
>                SVN_ERR(svn_wc_entries_read(&entries, parent_access, TRUE,
>                                            pool));
>                entry_in_parent = apr_hash_get(entries, bname,
> @@ -2517,11 +2535,12 @@ svn_wc_remove_from_revision_control(svn_
>                                  current_entry_name,
>                                  subpool);
>  
> -              if (svn_wc__adm_missing(adm_access, entrypath))
> +              if (svn_wc__adm_missing(adm_access, entrypath)
> +                  || current_entry->depth == svn_depth_exclude)
>                  {
> -                  /* The directory is already missing, so don't try to
> -                     recurse, just delete the entry in the parent
> -                     directory. */
> +                  /* The directory is either missing or excluded, 
> +                     so don't try to recurse, just delete the 
> +                     entry in the parent directory. */
>                    svn_wc__entry_remove(entries, current_entry_name);
>                  }
>                else
> @@ -2567,6 +2586,7 @@ svn_wc_remove_from_revision_control(svn_
>             full_path.  We need to remove that entry: */
>          if (! is_root)
>            {
> +            svn_wc_entry_t *dir_entry;
>              apr_hash_t *parent_entries;
>              svn_wc_adm_access_t *parent_access;
>  
> @@ -2576,8 +2596,19 @@ svn_wc_remove_from_revision_control(svn_
>                                          parent_dir, pool));
>              SVN_ERR(svn_wc_entries_read(&parent_entries, parent_access, TRUE,
>                                          pool));
> -            svn_wc__entry_remove(parent_entries, base_name);
> -            SVN_ERR(svn_wc__entries_write(parent_entries, parent_access, pool));
> +
> +            /* An exception: When the path is at svn_depth_exclude,
> +               the entry in the parent directory should be preserved
> +               for bookkeeping purpose. This only happens when the 
> +               function is called by svn_wc_crop_tree(). */
> +            dir_entry = apr_hash_get(parent_entries, base_name, 
> +                                     APR_HASH_KEY_STRING);
> +            if (dir_entry->depth != svn_depth_exclude)
> +              {
> +                svn_wc__entry_remove(parent_entries, base_name);
> +                SVN_ERR(svn_wc__entries_write(parent_entries, parent_access, pool));
> +
> +              }
>            }
>        }
>  
>
> Modified: trunk/subversion/libsvn_wc/ambient_depth_filter_editor.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/ambient_depth_filter_editor.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/ambient_depth_filter_editor.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/ambient_depth_filter_editor.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -132,19 +132,32 @@ make_dir_baton(struct dir_baton **d_p,
>    if (path)
>      d->path = svn_path_join(d->path, path, pool);
>  
> -  if (pb
> -      && (pb->ambient_depth == svn_depth_empty
> -          || pb->ambient_depth == svn_depth_files))
> +  /* The svn_depth_unknown means that: 1) pb is the anchor; 2) there
> +     is an non-null target, for which we are preparing the baton.
> +     This enables explicitly pull in the target. */
> +  if (pb && pb->ambient_depth != svn_depth_unknown)
>      {
> -      /* This is not a depth upgrade, and the parent directory is
> -         depth==empty or depth==files.  So if the parent doesn't
> -         already have an entry for the new dir, then the parent
> -         doesn't want the new dir at all, thus we should initialize
> -         it with ambiently_excluded=TRUE. */
>        const svn_wc_entry_t *entry;
> +      svn_boolean_t exclude;
>  
> -      SVN_ERR(svn_wc_entry(&entry, d->path, eb->adm_access, FALSE, pool));
> -      if (! entry)
> +      SVN_ERR(svn_wc_entry(&entry, d->path, eb->adm_access, TRUE, pool));
> +      if (pb->ambient_depth == svn_depth_empty
> +          || pb->ambient_depth == svn_depth_files)
> +        {
> +          /* This is not a depth upgrade, and the parent directory is
> +             depth==empty or depth==files.  So if the parent doesn't
> +             already have an entry for the new dir, then the parent
> +             doesn't want the new dir at all, thus we should initialize
> +             it with ambiently_excluded=TRUE. */
> +          exclude = (entry == NULL);
> +        }
> +      else
> +        {
> +          /* If the parent expect all children by default, only exclude
> +             it whenever it is explicitly marked as exclude. */
> +          exclude = (entry && (entry->depth == svn_depth_exclude));
> +        }
> +      if (exclude)
>          {
>            d->ambiently_excluded = TRUE;
>            *d_p = d;
>
> Modified: trunk/subversion/libsvn_wc/copy.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/copy.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/copy.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/copy.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -267,6 +267,10 @@ copy_added_dir_administratively(const ch
>            SVN_ERR(svn_wc_entry(&entry, src_fullpath, src_child_dir_access,
>                                 TRUE, subpool));
>  
> +          /* We do not need to handle excluded items here, since this function
> +             only deal with the sources which are not yet in the repos.
> +             Exclude flag is by definition not expected in such situation. */
> +
>            /* Recurse on directories; add files; ignore the rest. */
>            if (this_entry.filetype == APR_DIR)
>              {
> @@ -647,6 +651,9 @@ post_copy_cleanup(svn_wc_adm_access_t *a
>        kind = entry->kind;
>        deleted = entry->deleted;
>  
> +      if (entry->depth == svn_depth_exclude)
> +        continue;
> +
>        /* Convert deleted="true" into schedule="delete" for all
>           children (and grandchildren, if RECURSE is set) of the path
>           represented by ADM_ACCESS.  The result of this is that when
> @@ -862,8 +869,8 @@ svn_wc_copy2(const char *src_path,
>  {
>    svn_wc_adm_access_t *adm_access;
>    svn_node_kind_t src_kind;
> -  const char *dst_path;
> -  const svn_wc_entry_t *dst_entry, *src_entry;
> +  const char *dst_path, *target_path;
> +  const svn_wc_entry_t *dst_entry, *src_entry, *target_entry;
>  
>    SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, src_path, FALSE, -1,
>                                   cancel_func, cancel_baton, pool));
> @@ -888,6 +895,21 @@ svn_wc_copy2(const char *src_path,
>         _("Cannot copy to '%s' as it is scheduled for deletion"),
>         svn_path_local_style(svn_wc_adm_access_path(dst_parent), pool));
>  
> +  /* TODO(#2843): Rework the erroer report. */
> +  /* Check if the copy target is missing or hidden and thus not exist on the
> +     disk, before actually doing the file copy. */
> +  target_path = svn_path_join(dst_path, dst_basename, pool);
> +  SVN_ERR(svn_wc_entry(&target_entry, target_path, dst_parent, TRUE, pool));
> +  if (target_entry 
> +      && ((target_entry->depth == svn_depth_exclude) 
> +          || target_entry->absent))
> +    {
> +      return svn_error_createf
> +        (SVN_ERR_ENTRY_EXISTS, 
> +         NULL, _("'%s' is already under version control"),
> +         svn_path_local_style(target_path, pool)); 
> +    }
> +
>    SVN_ERR(svn_io_check_path(src_path, &src_kind, pool));
>  
>    if (src_kind == svn_node_file)
>
> Copied: trunk/subversion/libsvn_wc/crop.c (from r34105, branches/issue-2843-dev/subversion/libsvn_wc/crop.c)
> ==============================================================================
> --- /dev/null	00:00:00 1970	(empty, because file is newly added)
> +++ trunk/subversion/libsvn_wc/crop.c	Fri Nov  7 19:14:59 2008	(r34108, copy of r34105, branches/issue-2843-dev/subversion/libsvn_wc/crop.c)
> @@ -0,0 +1,320 @@
> +/*
> + * crop.c: Cropping the WC 
> + *
> + * ====================================================================
> + * Copyright (c) 2000-2007 CollabNet.  All rights reserved.
> + *
> + * This software is licensed as described in the file COPYING, which
> + * you should have received as part of this distribution.  The terms
> + * are also available at http://subversion.tigris.org/license-1.html.
> + * If newer versions of this license are posted there, you may use a
> + * newer version instead, at your option.
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals.  For exact contribution history, see the revision
> + * history and logs, available at http://subversion.tigris.org/.
> + * ====================================================================
> + */
> +
> +/* ==================================================================== */
> +
> +#include "svn_wc.h"
> +#include "lock.h"
> +#include "svn_pools.h"
> +#include "svn_error.h"
> +#include "svn_client.h"
> +#include "svn_error_codes.h"
> +#include "svn_path.h"
> +#include "entries.h"
> +
> +#include "svn_private_config.h"
> +
> +/* Evaluate EXPR.  If it returns an error, return that error, unless
> +   the error's code is SVN_ERR_WC_LEFT_LOCAL_MOD, in which case clear
> +   the error and do not return. */
> +#define IGNORE_LOCAL_MOD(expr)                                   \
> +  do {                                                           \
> +    svn_error_t *__temp = (expr);                                \
> +    if (__temp)                                                  \
> +      {                                                          \
> +        if (__temp->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)        \
> +          svn_error_clear(__temp);                               \
> +        else                                                     \
> +          return __temp;                                         \
> +      }                                                          \
> +  } while (0)
> +
> +/* Helper function that crops the children of the DIR_PATH, under the constraint
> + * of DEPTH. The DIR_PATH itself will never be cropped. The ADM_ACCESS is the
> + * access baton that contains DIR_PATH. And the whole subtree should have been
> + * locked.
> + *
> + * If NOTIFY_FUNC is not null, each file and ROOT of subtree will be reported
> + * upon remove.
> + */
> +static svn_error_t *
> +crop_children(svn_wc_adm_access_t *adm_access,
> +              const char *dir_path,
> +              svn_depth_t depth,
> +              svn_wc_notify_func2_t notify_func,
> +              void *notify_baton,
> +              svn_cancel_func_t cancel_func,
> +              void *cancel_baton,
> +              apr_pool_t *pool)
> +{
> +  apr_hash_t *entries;
> +  apr_hash_index_t *hi;
> +  svn_wc_adm_access_t *dir_access;
> +  svn_wc_entry_t *dot_entry;
> +  apr_pool_t *subpool = svn_pool_create(pool), *iterpool;
> +
> +  SVN_ERR(svn_wc_adm_retrieve(&dir_access, adm_access, dir_path, subpool));
> +  SVN_ERR(svn_wc_entries_read(&entries, dir_access, TRUE, subpool));
> +  dot_entry = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR,
> +                           APR_HASH_KEY_STRING);
> +
> +  /* Update the depth of target first, if needed. */
> +  if (dot_entry->depth > depth)
> +    {
> +      dot_entry->depth = depth;
> +      SVN_ERR(svn_wc__entries_write(entries, dir_access, subpool));
> +    }
> +
> +  /* Looping over current directory's SVN entries: */
> +  iterpool = svn_pool_create(subpool);
> +
> +  for (hi = apr_hash_first(subpool, entries); hi; hi = apr_hash_next(hi))
> +    {
> +      const void *key;
> +      const char *this_path;
> +      void *val;
> +      apr_ssize_t klen;
> +      svn_wc_entry_t *current_entry;
> +      svn_pool_clear(iterpool);
> +
> +      /* Get the next entry */
> +      apr_hash_this(hi, &key, &klen, &val);
> +      if (! strcmp(key, SVN_WC_ENTRY_THIS_DIR))
> +        continue;
> +
> +      current_entry = val;
> +      this_path = svn_path_join(dir_path, current_entry->name, iterpool); 
> +
> +      if (current_entry->kind == svn_node_file)
> +        {
> +          /* We currently crop on a directory basis. So don't worry about
> +             svn_depth_exclude here. And even we permit excluding a single
> +             file in the future, svn_wc_remove_from_revision_control() can
> +             also handle it. We only need to skip the notification in that
> +             case. */
> +          if (depth == svn_depth_empty)
> +            IGNORE_LOCAL_MOD
> +              (svn_wc_remove_from_revision_control(dir_access,
> +                                                   current_entry->name,
> +                                                   TRUE, /* destroy */
> +                                                   FALSE, /* instant error */
> +                                                   cancel_func,
> +                                                   cancel_baton,
> +                                                   iterpool));
> +          else
> +            continue;
> +
> +        }
> +      else if (current_entry->kind == svn_node_dir)
> +        {
> +          if (current_entry->depth == svn_depth_exclude)
> +            {
> +              /* Preserve the excluded entry if the parent need it.
> +                 Anyway, don't report on excluded subdir, since they are
> +                 logically not exist. */
> +              if (depth < svn_depth_immediates)
> +                {
> +                  svn_wc__entry_remove(entries, current_entry->name);
> +                  SVN_ERR(svn_wc__entries_write(entries, dir_access, iterpool));
> +                }
> +              continue;
> +            }
> +          else if (depth < svn_depth_immediates)
> +            {
> +              svn_wc_adm_access_t *child_access;
> +              SVN_ERR(svn_wc_adm_retrieve(&child_access, dir_access,
> +                                          this_path, iterpool));
> +
> +              IGNORE_LOCAL_MOD
> +                (svn_wc_remove_from_revision_control(child_access,
> +                                                     SVN_WC_ENTRY_THIS_DIR,
> +                                                     TRUE, /* destroy */
> +                                                     FALSE, /* instant error */
> +                                                     cancel_func,
> +                                                     cancel_baton,
> +                                                     iterpool));
> +            }
> +          else
> +            {
> +              SVN_ERR(crop_children(dir_access,
> +                                    this_path, 
> +                                    svn_depth_empty, 
> +                                    notify_func,
> +                                    notify_baton,
> +                                    cancel_func, 
> +                                    cancel_baton, 
> +                                    iterpool));
> +              continue;
> +            }
> +        }
> +      else
> +        {
> +          return svn_error_createf
> +            (SVN_ERR_NODE_UNKNOWN_KIND, NULL, _("Unknown entry kind for '%s'"),
> +             svn_path_local_style(this_path, pool));
> +        }
> +
> +      if (notify_func)
> +        {
> +          svn_wc_notify_t *notify;
> +          notify = svn_wc_create_notify(this_path,
> +                                        svn_wc_notify_delete,
> +                                        iterpool);
> +          (*notify_func)(notify_baton, notify, iterpool);
> +        }
> +    }
> +
> +  svn_pool_destroy(subpool);
> +
> +  return SVN_NO_ERROR;
> +}
> +
> +svn_error_t *
> +svn_wc_crop_tree(svn_wc_adm_access_t *anchor,
> +                 const char *target,
> +                 svn_depth_t depth,
> +                 svn_wc_notify_func2_t notify_func,
> +                 void *notify_baton,
> +                 svn_cancel_func_t cancel_func,
> +                 void *cancel_baton,
> +                 apr_pool_t *pool)
> +{
> +  const svn_wc_entry_t *entry;
> +  const char *full_path;
> +  svn_wc_adm_access_t *dir_access;
> +
> +  /* Only makes sense when the depth is restrictive. */
> +  if (!(depth >= svn_depth_exclude && depth < svn_depth_infinity))
> +    return SVN_NO_ERROR;
> +
> +  /* Only makes sense to crop a dir target. */
> +  full_path = svn_path_join(svn_wc_adm_access_path(anchor), target, pool);
> +  SVN_ERR(svn_wc_entry(&entry, full_path, anchor, FALSE, pool));
> +  if (!entry || entry->kind != svn_node_dir)
> +    return SVN_NO_ERROR;
> +
> +  /* Don't bother to crop if the target is scheduled delete. */
> +  if (entry->schedule == svn_wc_schedule_delete)
> +    return svn_error_createf
> +      (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
> +       _("Cannot crop '%s': it is going to be removed from repository."
> +         " Try commit instead."),
> +       svn_path_local_style(full_path, pool));
> +
> +  /* Crop the target itself if we are requested to. */
> +  if (depth == svn_depth_exclude)
> +    {
> +      svn_boolean_t switched, entry_in_repos;
> +      const svn_wc_entry_t *parent_entry = NULL;
> +      svn_wc_adm_access_t *p_access;
> +
> +      /* Safeguard on bad target. */
> +      if (*full_path == 0)
> +        return svn_error_createf
> +          (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
> +           _("Cannot exclude current directory."));
> +
> +      if (svn_dirent_is_root(full_path, strlen(full_path)))
> +        return svn_error_createf
> +          (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
> +           _("Cannot exclude root directory."));
> +
> +      /* This simulates the logic of svn_wc_is_wc_root(). */
> +        {
> +          const char *bname, *pname;
> +          svn_error_t *err = NULL;
> +          svn_path_split(full_path, &pname, &bname, pool);
> +          SVN_ERR(svn_wc__adm_retrieve_internal(&p_access, anchor, pname,
> +                                                pool));
> +          if (! p_access)
> +            err = svn_wc_adm_probe_open3(&p_access, NULL, pname, FALSE, 0,
> +                                         NULL, NULL, pool);
> +
> +          if (! err)
> +            err = svn_wc_entry(&parent_entry, pname, p_access, FALSE, pool);
> +
> +          if (err)
> +            svn_error_clear(err);
> +
> +          switched 
> +            = parent_entry && strcmp(entry->url, 
> +                                     svn_path_url_add_component
> +                                     (parent_entry->url, bname, pool));
> +
> +          /* The server simply do not accept excluded link_path and thus
> +             switched path can not be excluede. Just completely prohibit this
> +             situation. */
> +          if (switched)
> +            return svn_error_createf
> +              (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
> +               _("Cannot crop '%s': it is a switched path."),
> +               svn_path_local_style(full_path, pool));
> +        }
> +
> +      /* If the target entry is just added without history, it does not exist
> +         in the repos (in which case we won't exclude it). */
> +      entry_in_repos
> +        = ! ((entry->schedule == svn_wc_schedule_add
> +              || entry->schedule == svn_wc_schedule_replace)
> +             && ! entry->copied);
> +
> +      /* Mark the target as excluded, if the parent requires it by
> +         default. */
> +      if (parent_entry && entry_in_repos
> +          && (parent_entry->depth > svn_depth_files))
> +        {
> +          svn_wc_entry_t *target_entry;
> +          apr_hash_t *parent_entries;
> +          SVN_ERR(svn_wc_entries_read(&parent_entries, p_access, 
> +                                      FALSE, pool));
> +
> +          target_entry = apr_hash_get(parent_entries, 
> +                                      svn_path_basename(full_path, pool),
> +                                      APR_HASH_KEY_STRING);
> +
> +          target_entry->depth = svn_depth_exclude;
> +          SVN_ERR(svn_wc__entries_write(parent_entries, anchor, pool));
> +        }
> +
> +      /* TODO(#2843): Do we need to restore the modified depth if the user
> +         cancel this operation? */
> +      SVN_ERR(svn_wc_adm_retrieve(&dir_access, anchor, full_path, pool));
> +      IGNORE_LOCAL_MOD
> +        (svn_wc_remove_from_revision_control(dir_access,
> +                                             SVN_WC_ENTRY_THIS_DIR,
> +                                             TRUE, /* destroy */
> +                                             FALSE, /* instant error */
> +                                             cancel_func,
> +                                             cancel_baton,
> +                                             pool));
> +
> +      if (notify_func)
> +        {
> +          svn_wc_notify_t *notify;
> +          notify = svn_wc_create_notify(full_path,
> +                                        svn_wc_notify_delete,
> +                                        pool);
> +          (*notify_func)(notify_baton, notify, pool);
> +        }
> +      return SVN_NO_ERROR;
> +    }
> +
> +  return crop_children(anchor, full_path, depth,
> +                       notify_func, notify_baton,
> +                       cancel_func, cancel_baton, pool);
> +}
>
> Modified: trunk/subversion/libsvn_wc/entries.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/entries.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/entries.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/entries.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -667,9 +667,29 @@ read_entry(svn_wc_entry_t **new_entry,
>      const char *result;
>      SVN_ERR(read_val(&result, buf, end));
>      if (result)
> -      entry->depth = svn_depth_from_word(result);
> +      {
> +        svn_boolean_t invalid;
> +        svn_boolean_t is_this_dir;
> +
> +        entry->depth = svn_depth_from_word(result);
> +
> +        /* Verify the depth value: 
> +           THIS_DIR should not have an excluded value and SUB_DIR should only
> +           have excluded value. Remember that infinity value is not stored and
> +           should not show up here. Otherwise, something bad may have
> +           happened. However, infinity value itself will always be okay. */
> +        is_this_dir = !name;
> +        /* '!=': XOR */
> +        invalid = is_this_dir != (entry->depth != svn_depth_exclude);
> +        if (entry->depth != svn_depth_infinity && invalid)
> +          return svn_error_createf
> +            (SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
> +             _("Entry '%s' has invalid depth"),
> +             (name ? name : SVN_WC_ENTRY_THIS_DIR));
> +      }
>      else
>        entry->depth = svn_depth_infinity;
> +
>    }
>    MAYBE_DONE;
>  
> @@ -1415,8 +1435,12 @@ read_entries(svn_wc_adm_access_t *adm_ac
>  
>            ++curp;
>            ++entryno;
> -          if (!entry_is_hidden(entry) || show_hidden)
> -            apr_hash_set(entries, entry->name, APR_HASH_KEY_STRING, entry);
> +
> +          if ((entry->depth != svn_depth_exclude)
> +              || (!entry_is_hidden(entry) || show_hidden))
> +            {
> +              apr_hash_set(entries, entry->name, APR_HASH_KEY_STRING, entry);
> +            }
>          }
>      }
>  
> @@ -1877,7 +1901,9 @@ write_entry(svn_stringbuf_t *buf,
>    }
>  
>    /* Depth. */
> -  if (is_subdir || entry->depth == svn_depth_infinity)
> +  /* Accept `exclude' for subdir entry. */
> +  if ((is_subdir && entry->depth != svn_depth_exclude)
> +      || entry->depth == svn_depth_infinity)
>      {
>        write_val(buf, NULL, 0);
>      }
> @@ -3266,7 +3292,7 @@ svn_wc_walk_entries3(const char *path,
>                                 svn_path_local_style(path, pool)),
>         walk_baton, pool);
>  
> -  if (entry->kind == svn_node_file)
> +  if (entry->kind == svn_node_file || entry->depth == svn_depth_exclude)
>      return walk_callbacks->handle_error
>        (path, walk_callbacks->found_entry(path, entry, walk_baton, pool),
>         walk_baton, pool);
>
> Modified: trunk/subversion/libsvn_wc/lock.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/lock.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/lock.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/lock.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -698,6 +698,11 @@ do_open(svn_wc_adm_access_t **adm_access
>            if (entry->kind != svn_node_dir
>                || ! strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR))
>              continue;
> +
> +          /* Also skip the excluded subdir. */
> +          if (entry->depth == svn_depth_exclude)
> +            continue;
> +
>            entry_path = svn_path_join(path, entry->name, subpool);
>  
>            /* Don't use the subpool pool here, the lock needs to persist */
> @@ -1595,7 +1600,7 @@ prune_deleted(svn_wc_adm_access_t *adm_a
>            if ((entry->deleted
>                 && (entry->schedule != svn_wc_schedule_add)
>                 && (entry->schedule != svn_wc_schedule_replace))
> -              || entry->absent)
> +              || entry->absent || (entry->depth == svn_depth_exclude))
>              break;
>          }
>  
> @@ -1618,7 +1623,8 @@ prune_deleted(svn_wc_adm_access_t *adm_a
>  
>            apr_hash_this(hi, &key, NULL, &val);
>            entry = val;
> -          if (((entry->deleted == FALSE) && (entry->absent == FALSE))
> +          if (((entry->deleted == FALSE) && (entry->absent == FALSE)
> +               && (entry->depth != svn_depth_exclude))
>                || (entry->schedule == svn_wc_schedule_add)
>                || (entry->schedule == svn_wc_schedule_replace))
>              {
>
> Modified: trunk/subversion/libsvn_wc/log.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/log.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/log.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/log.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -1003,7 +1003,8 @@ remove_deleted_entry(void *baton, const 
>    const svn_wc_entry_t *cur_entry = val;
>    svn_wc_adm_access_t *entry_access;
>  
> -  /* Skip each entry that isn't scheduled for deletion. */
> +  /* Skip each entry that isn't scheduled for deletion. This gracefully
> +     includes excluded item. */
>    if (cur_entry->schedule != svn_wc_schedule_delete)
>      return SVN_NO_ERROR;
>  
> @@ -1163,7 +1164,7 @@ log_do_committed(struct log_runner *logg
>            SVN_ERR(svn_wc_entry(&parentry,
>                                 svn_wc_adm_access_path(loggy->adm_access),
>                                 loggy->adm_access,
> -                               TRUE, pool));
> +                               FALSE, pool));
>            if (new_rev > parentry->revision)
>              {
>                /* ...then the parent's revision is now officially a
>
> Modified: trunk/subversion/libsvn_wc/props.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/props.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/props.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/props.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -480,7 +480,10 @@ svn_wc__working_props_committed(const ch
>    svn_wc_adm_access_t *mod_access;
>  
>  
> -  SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, TRUE, pool));
> +  /* The path is ensured not an excluded path. */
> +  /* TODO(#2843) It seems that there is no need to 
> +     reveal hidden entry here? */
> +  SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, FALSE, pool));
>  
>    SVN_ERR(svn_wc__prop_path(&working, path, entry->kind,
>                              svn_wc__props_working, FALSE, pool));
> @@ -831,7 +834,9 @@ svn_wc__loggy_revert_props_create(svn_st
>    const char *tmp_rprop;
>    svn_node_kind_t kind;
>  
> -  SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, TRUE, pool));
> +  /* TODO(#2843) The current caller ensures that PATH will not be an excluded
> +     item. But do we really need show_hidden = TRUE here? */
> +  SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, FALSE, pool));
>  
>    SVN_ERR(svn_wc__prop_path(&dst_rprop, path,
>                              entry->kind, svn_wc__props_revert, FALSE, pool));
> @@ -941,7 +946,9 @@ svn_wc__loggy_revert_props_restore(svn_s
>    const svn_wc_entry_t *entry;
>    const char *revert_file, *base_file;
>  
> -  SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, TRUE, pool));
> +  /* TODO(#2843) The current caller ensures that PATH will not be an excluded
> +     item. But do we really need show_hidden = TRUE here? */
> +  SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, FALSE, pool));
>  
>    SVN_ERR(svn_wc__prop_path(&base_file, path, entry->kind, svn_wc__props_base,
>                              FALSE, pool));
> @@ -2212,10 +2219,10 @@ svn_wc_prop_list(apr_hash_t **props,
>  {
>    const svn_wc_entry_t *entry;
>  
> -  SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, pool));
> +  SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
>  
>    /* if there is no entry, 'path' is not under version control and
> -     therefore has no props */
> +     therefore has no props. */
>    if (! entry)
>      {
>        *props = apr_hash_make(pool);
> @@ -2263,7 +2270,7 @@ svn_wc_prop_get(const svn_string_t **val
>    enum svn_prop_kind kind = svn_property_kind(NULL, name);
>    const svn_wc_entry_t *entry;
>  
> -  SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, pool));
> +  SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
>  
>    if (entry == NULL)
>      {
> @@ -2817,7 +2824,7 @@ modified_props(svn_boolean_t *modified_p
>    if (want_props)
>      *which_props = apr_hash_make(pool);
>  
> -  SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, subpool));
> +  SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, subpool));
>  
>    /* If we have no entry, we can't have any prop mods. */
>    if (! entry)
>
> Modified: trunk/subversion/libsvn_wc/relocate.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/relocate.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/relocate.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/relocate.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -128,7 +128,8 @@ svn_wc_relocate3(const char *path,
>    if (! entry)
>      return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, NULL, NULL);
>  
> -  if (entry->kind == svn_node_file)
> +  if (entry->kind == svn_node_file
> +      || entry->depth == svn_depth_exclude)
>      return relocate_entry(adm_access, entry, from, to,
>                            validator, validator_baton, TRUE /* sync */,
>                            pool);
> @@ -160,7 +161,8 @@ svn_wc_relocate3(const char *path,
>  
>        if (recurse && (entry->kind == svn_node_dir)
>            && (! entry->deleted || (entry->schedule == svn_wc_schedule_add))
> -          && ! entry->absent)
> +          && ! entry->absent
> +          && (entry->depth != svn_depth_exclude))
>          {
>            svn_wc_adm_access_t *subdir_access;
>            const char *subdir = svn_path_join(path, key, subpool);
>
> Modified: trunk/subversion/libsvn_wc/update_editor.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_wc/update_editor.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/libsvn_wc/update_editor.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/libsvn_wc/update_editor.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -549,6 +549,13 @@ make_dir_baton(struct dir_baton **d_p,
>  }
>  
>  
> +/* Forward declaration. */
> +static svn_error_t *
> +do_entry_deletion(struct edit_baton *eb,
> +                  const char *parent_path,
> +                  const char *path,
> +                  int *log_number,
> +                  apr_pool_t *pool);
>  
>  /* Helper for maybe_bump_dir_info():
>  
> @@ -574,7 +581,41 @@ complete_directory(struct edit_baton *eb
>    /* If this is the root directory and there is a target, we can't
>       mark this directory complete. */
>    if (is_root_dir && *eb->target)
> -    return SVN_NO_ERROR;
> +    {
> +      /* Before we can finish, we may need to clear the exclude flag for
> +         target. Also give a chance to the target that is explicitly pulled
> +         in. */
> +      if (eb->depth_is_sticky || *eb->target)
> +        {
> +          svn_wc_adm_access_t *target_access;
> +          SVN_ERR(svn_wc_adm_retrieve(&adm_access, 
> +                                      eb->adm_access, path, pool));
> +          SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE, pool));
> +          entry = apr_hash_get(entries, eb->target, APR_HASH_KEY_STRING);
> +          if (entry && entry->depth == svn_depth_exclude)
> +            {
> +              char * full_target;
> +              /* There is a small chance that the target is gone in the
> +                 repository.  If so, we should get rid of the entry
> +                 (and thus get rid of the exclude flag) now. */
> +              full_target = svn_path_join(eb->anchor, eb->target, pool);
> +              SVN_ERR(svn_wc__adm_retrieve_internal
> +                      (&target_access, eb->adm_access, full_target, pool));
> +              if (!target_access && entry->kind == svn_node_dir)
> +                {
> +                  int log_number = 0;
> +                  SVN_ERR(do_entry_deletion(eb, eb->anchor, eb->target,
> +                                            &log_number, pool));
> +                }
> +              else
> +                {
> +                  entry->depth = svn_depth_infinity;
> +                  SVN_ERR(svn_wc__entries_write(entries, adm_access, pool));
> +                }
> +            }
> +        }
> +      return SVN_NO_ERROR;
> +    }
>  
>    /* All operations are on the in-memory entries hash. */
>    SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access, path, pool));
> @@ -642,21 +683,27 @@ complete_directory(struct edit_baton *eb
>          {
>            const char *child_path = svn_path_join(path, name, subpool);
>  
> -          if ((svn_wc__adm_missing(adm_access, child_path))
> -              && (! current_entry->absent)
> -              && (current_entry->schedule != svn_wc_schedule_add))
> +          if (current_entry->depth == svn_depth_exclude)
>              {
> -              svn_wc__entry_remove(entries, name);
> -              if (eb->notify_func)
> -                {
> -                  svn_wc_notify_t *notify
> -                    = svn_wc_create_notify(child_path,
> -                                           svn_wc_notify_update_delete,
> -                                           subpool);
> -                  notify->kind = current_entry->kind;
> -                  (* eb->notify_func)(eb->notify_baton, notify, subpool);
> -                }
> -            }
> +              /* Clear the exclude flag if it is pulled in again. */
> +              if (eb->depth_is_sticky 
> +                  && eb->requested_depth >= svn_depth_immediates)
> +                current_entry->depth = svn_depth_infinity;
> +            } else if ((svn_wc__adm_missing(adm_access, child_path))
> +                       && (! current_entry->absent)
> +                       && (current_entry->schedule != svn_wc_schedule_add))
> +              {
> +                svn_wc__entry_remove(entries, name);
> +                if (eb->notify_func)
> +                  {
> +                    svn_wc_notify_t *notify
> +                      = svn_wc_create_notify(child_path,
> +                                             svn_wc_notify_update_delete,
> +                                             subpool);
> +                    notify->kind = current_entry->kind;
> +                    (* eb->notify_func)(eb->notify_baton, notify, subpool);
> +                  }
> +              }
>          }
>      }
>  
> @@ -1469,7 +1516,20 @@ do_entry_deletion(struct edit_baton *eb,
>    SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access,
>                                parent_path, pool));
>  
> -  SVN_ERR(svn_wc__entry_versioned(&entry, full_path, adm_access, FALSE, pool));
> +  SVN_ERR(svn_wc__entry_versioned(&entry, full_path, adm_access, TRUE, pool));
> +
> +  /* Receive the remote removal of excluded entry. Do not notify. */
> +  if (entry->depth == svn_depth_exclude)
> +    {
> +      apr_hash_t *entries;
> +      const char *base_name = svn_path_basename(full_path, pool);
> +      SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE, pool));
> +      svn_wc__entry_remove(entries, base_name);
> +      SVN_ERR(svn_wc__entries_write(entries, adm_access, pool));
> +      if (strcmp(path, eb->target) == 0)
> +        eb->target_deleted = TRUE;
> +      return SVN_NO_ERROR;
> +    }
>  
>    SVN_ERR(check_tree_conflict(&tree_conflict, eb, log_item, full_path, entry,
>                                adm_access, svn_wc_conflict_action_delete, pool));
> @@ -3890,41 +3950,25 @@ make_editor(svn_revnum_t *target_revisio
>    inner_editor = tree_editor;
>    inner_baton = eb;
>  
> -  /* If our requested depth is sticky, we'll raise an error if asked
> -     to make our target more shallow, which is currently unsupported.
> -
> -     Otherwise, if our requested depth is *not* sticky, then we need
> -     to limit the scope of our operation to the ambient depths present
> -     in the working copy already.  If a depth was explicitly
> -     requested, libsvn_delta/depth_filter_editor.c will ensure that we
> -     never see editor calls that extend beyond the scope of the
> -     requested depth.  But even what we do so might extend beyond the
> -     scope of our ambient depth.  So we use another filtering editor
> -     to avoid modifying the ambient working copy depth when not asked
> -     to do so.  (This can also be skipped if the server understands
> -     consider letting the depth RA capability percolate down to this
> -     level.) */
> -  if (depth_is_sticky)
> -    {
> -      const svn_wc_entry_t *target_entry;
> -      SVN_ERR(svn_wc_entry(&target_entry, svn_path_join(anchor, target, pool),
> -                           adm_access, FALSE, pool));
> -      if (target_entry && (target_entry->depth > depth))
> -        return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
> -                                 _("Shallowing of working copy depths is not "
> -                                   "yet supported"));
> -    }
> -  else
> -    {
> -      SVN_ERR(svn_wc__ambient_depth_filter_editor(&inner_editor,
> -                                                  &inner_baton,
> -                                                  inner_editor,
> -                                                  inner_baton,
> -                                                  anchor,
> -                                                  target,
> -                                                  adm_access,
> -                                                  pool));
> -    }
> +  /* We need to limit the scope of our operation to the ambient depths
> +     present in the working copy already, but only if the requested
> +     depth is not sticky. If a depth was explicitly requested, 
> +     libsvn_delta/depth_filter_editor.c will ensure that we never see 
> +     editor calls that extend beyond the scope of the requested depth.
> +     But even what we do so might extend beyond the scope of our 
> +     ambient depth.  So we use another filtering editor to avoid 
> +     modifying the ambient working copy depth when not asked to do so.
> +     (This can also be skipped if the server understands depth; consider
> +     letting the depth RA capability percolate down to this level.) */
> +  if (!depth_is_sticky)
> +    SVN_ERR(svn_wc__ambient_depth_filter_editor(&inner_editor,
> +                                                &inner_baton,
> +                                                inner_editor,
> +                                                inner_baton,
> +                                                anchor,
> +                                                target,
> +                                                adm_access,
> +                                                pool));
>  
>    return svn_delta_get_cancellation_editor(cancel_func,
>                                             cancel_baton,
>
> Modified: trunk/subversion/svn/main.c
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/svn/main.c?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/svn/main.c	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/svn/main.c	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -1317,13 +1317,13 @@ main(int argc, const char *argv[])
>                                 _("Error converting depth "
>                                   "from locale to UTF8")), pool, "svn: ");
>          opt_state.set_depth = svn_depth_from_word(utf8_opt_arg);
> -        if (opt_state.set_depth == svn_depth_unknown
> -            || opt_state.set_depth == svn_depth_exclude)
> +        /* svn_depth_exclude is okay for --set-depth. */
> +        if (opt_state.set_depth == svn_depth_unknown)
>            {
>              return svn_cmdline_handle_exit_error
>                (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
>                                   _("'%s' is not a valid depth; try "
> -                                   "'empty', 'files', 'immediates', "
> +                                   "'exclude', 'empty', 'files', 'immediates', "
>                                     "or 'infinity'"),
>                                   utf8_opt_arg), pool, "svn: ");
>            }
>
> Modified: trunk/subversion/tests/cmdline/depth_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/depth_tests.py?pathrev=34108&r1=34107&r2=34108
> ==============================================================================
> --- trunk/subversion/tests/cmdline/depth_tests.py	Fri Nov  7 15:41:58 2008	(r34107)
> +++ trunk/subversion/tests/cmdline/depth_tests.py	Fri Nov  7 19:14:59 2008	(r34108)
> @@ -1450,7 +1450,6 @@ def depthy_update_above_dir_to_be_delete
>  #----------------------------------------------------------------------
>  
>  # Tests for deselection interface (a.k.a folding subtrees).
> -# XFail until issue #2843 is resolved.
>  #----------------------------------------------------------------------
>  def depth_folding_clean_trees_1(sbox):
>    "gradually fold wc from depth=infinity to empty"
> @@ -1474,15 +1473,16 @@ def depth_folding_clean_trees_1(sbox):
>    A_path = os.path.join(wc_dir, 'A')
>    C_path = os.path.join(A_path, 'C')
>    B_path = os.path.join(A_path, 'B')
> +  D_path = os.path.join(A_path, 'D')
>    E_path = os.path.join(B_path, 'E')
>    F_path = os.path.join(B_path, 'F')
> -  D_path = os.path.join(A_path, 'D')
> -  H_path = os.path.join(A_path, 'H')
> +  G_path = os.path.join(D_path, 'G')
> +  H_path = os.path.join(D_path, 'H')
>  
>    # Run 'svn up --set-depth=immediates' to directory A/B/E.
>    # This is an infinity=>immediates folding, changes on metadata only
>    expected_output = svntest.wc.State(wc_dir, {})
> -  expected_status = svntest.actions.get_virginal_state('', 1)
> +  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
>    expected_disk = svntest.main.greek_state.copy()
>    svntest.actions.run_and_verify_update(wc_dir,
>                                          expected_output,
> @@ -1645,8 +1645,8 @@ def depth_folding_clean_trees_1(sbox):
>                                          expected_status,
>                                          None, None,
>                                          None, None, None, None,
> -                                        '--set-depth', 'files')
> -  verify_depth(None, "files")
> +                                        '--set-depth', 'files', wc_dir)
> +  verify_depth(None, "files", wc_dir)
>  
>  
>  #------------------------------------------------------------------------------
> @@ -1675,7 +1675,8 @@ def depth_folding_clean_trees_2(sbox):
>    verify_depth(None, "immediates", A_path)
>  
>    # pull in directory D at infinity
> -  svntest.actions.run_and_verify_svn(None, None, [], 'up', D_path)
> +  svntest.actions.run_and_verify_svn(None, None, [], 
> +                                     'up', '--set-depth', 'infinity', D_path)
>  
>    # Run 'svn up --set-depth=immediates' to directory A/D.
>    # This is an infinity=>immediates folding
> @@ -1699,7 +1700,7 @@ def depth_folding_clean_trees_2(sbox):
>      'A/D/G'          : Item(status='  ', wc_rev=1),
>      'A/D/H'          : Item(status='  ', wc_rev=1)
>      })
> -  expected_disk = svntest.wc.State(wc_dir, {
> +  expected_disk = svntest.wc.State('', {
>      'iota'        : Item(contents="This is the file 'iota'.\n"),
>      'A'           : Item(contents=None),
>      'A/mu'        : Item(contents="This is the file 'mu'.\n"),
> @@ -1708,7 +1709,7 @@ def depth_folding_clean_trees_2(sbox):
>      'A/D'         : Item(contents=None),
>      'A/D/gamma'   : Item(contents="This is the file 'gamma'.\n"),
>      'A/D/G'       : Item(contents=None),
> -    'A/D/H'       : Item(contents=None)
> +    'A/D/H'       : Item(contents=None),
>      })
>    svntest.actions.run_and_verify_update(wc_dir,
>                                          expected_output,
> @@ -1742,20 +1743,14 @@ def depth_folding_clean_trees_2(sbox):
>  
>    # pull in directory D at infinity
>    svntest.actions.run_and_verify_svn(None, None, [],
> -                                     'up', D_path)
> +                                     'up', '--set-depth', 'infinity', D_path)
>  
>    # Run 'svn up --set-depth=immediates' to directory A.
>    # This is an mixed(immediates+infinity)=>immediates folding
>    expected_output = svntest.wc.State(wc_dir, {
>      'A/D/gamma'      : Item(status='D '),
>      'A/D/G'          : Item(status='D '),
> -    'A/D/G/pi'       : Item(status='D '),
> -    'A/D/G/rho'      : Item(status='D '),
> -    'A/D/G/tau'      : Item(status='D '),
>      'A/D/H'          : Item(status='D '),
> -    'A/D/H/chi'      : Item(status='D '),
> -    'A/D/H/psi'      : Item(status='D '),
> -    'A/D/H/omega'    : Item(status='D ')
>      })
>    svntest.actions.run_and_verify_update(wc_dir,
>                                          expected_output,
> @@ -1769,7 +1764,7 @@ def depth_folding_clean_trees_2(sbox):
>  
>    # pull in directory D at files
>    svntest.actions.run_and_verify_svn(None, None, [],
> -                                     'up', '--depth', 'files', D_path)
> +                                     'up', '--set-depth', 'files', D_path)
>  
>    # Run 'svn up --set-depth=immediates' to directory A.
>    # This is an mixed(immediates+files)=>immediates folding
> @@ -1786,30 +1781,30 @@ def depth_folding_clean_trees_2(sbox):
>    verify_depth(None, "immediates", A_path)
>    verify_depth(None, "empty", D_path)
>  
> -  # Run 'svn up --set-depth=empty' to directory A.
> -  # This is an immediates=>empty folding, the directory A should be deleted
> -  # too since the parent directory is at files/empty
> -  expected_output = svntest.wc.State(wc_dir, {
> -    'A'              : Item(status='D '),
> -    'A/mu'           : Item(status='D '),
> -    'A/D'            : Item(status='D '),
> -    'A/C'            : Item(status='D '),
> -    'A/B'            : Item(status='D ')
> -    })
> -  expected_status = svntest.wc.State(wc_dir, {
> -    ''               : Item(status='  ', wc_rev=1),
> -    'iota'           : Item(status='  ', wc_rev=1)
> -    })
> -  expected_disk = svntest.wc.State(wc_dir, {
> -    'iota'        : Item(contents="This is the file 'iota'.\n")
> -    })
> -  svntest.actions.run_and_verify_update(wc_dir,
> -                                        expected_output,
> -                                        expected_disk,
> -                                        expected_status,
> -                                        None, None,
> -                                        None, None, None, None,
> -                                        '--set-depth', 'empty', A_path)
> +#  Comment the following out, since cropping out the root of tree is now
> +#  handled by svn_depth_exclude and should have a separate test case for all
> +#  influenced commands.
> +#
> +#  # Run 'svn up --set-depth=empty' to directory A.
> +#  # This is an immediates=>empty folding, the directory A should be deleted
> +#  # too since the parent directory is at files/empty
> +#  expected_output = svntest.wc.State(wc_dir, {
> +#    'A'              : Item(status='D '),
> +#    })
> +#  expected_status = svntest.wc.State(wc_dir, {
> +#    ''               : Item(status='  ', wc_rev=1),
> +#    'iota'           : Item(status='  ', wc_rev=1)
> +#    })
> +#  expected_disk = svntest.wc.State('', {
> +#    'iota'        : Item(contents="This is the file 'iota'.\n")
> +#    })
> +#  svntest.actions.run_and_verify_update(wc_dir,
> +#                                        expected_output,
> +#                                        expected_disk,
> +#                                        expected_status,
> +#                                        None, None,
> +#                                        None, None, None, None,
> +#                                        '--set-depth', 'empty', A_path)
>  
>  def depth_fold_expand_clean_trees(sbox):
>    "expand target while contracting subtree"
> @@ -1844,13 +1839,7 @@ def depth_fold_expand_clean_trees(sbox):
>      'A/C'            : Item(status='A '),
>      'A/D/gamma'      : Item(status='D '),
>      'A/D/G'          : Item(status='D '),
> -    'A/D/G/pi'       : Item(status='D '),
> -    'A/D/G/rho'      : Item(status='D '),
> -    'A/D/G/tau'      : Item(status='D '),
>      'A/D/H'          : Item(status='D '),
> -    'A/D/H/chi'      : Item(status='D '),
> -    'A/D/H/psi'      : Item(status='D '),
> -    'A/D/H/omega'    : Item(status='D ')
>      })
>    expected_status = svntest.wc.State(wc_dir, {
>      ''               : Item(status='  ', wc_rev=1),
> @@ -1860,7 +1849,7 @@ def depth_fold_expand_clean_trees(sbox):
>      'A/C'            : Item(status='  ', wc_rev=1),
>      'A/D'            : Item(status='  ', wc_rev=1)
>      })
> -  expected_disk = svntest.wc.State(wc_dir, {
> +  expected_disk = svntest.wc.State('', {
>      'A'           : Item(contents=None),
>      'A/mu'        : Item(contents="This is the file 'mu'.\n"),
>      'A/B'         : Item(contents=None),
> @@ -1881,25 +1870,16 @@ def depth_fold_expand_clean_trees(sbox):
>  
>    # Run 'svn up --set-depth=files' to directory A in other_wc. This both
>    # removes directory D and expands directory A to files
> -  expected_output = svntest.wc.State(wc_dir, {
> +  expected_output = svntest.wc.State(other_wc, {
>      'A/mu'           : Item(status='A '),
>      'A/D'            : Item(status='D '),
> -    'A/D/gamma'      : Item(status='D '),
> -    'A/D/G'          : Item(status='D '),
> -    'A/D/G/pi'       : Item(status='D '),
> -    'A/D/G/rho'      : Item(status='D '),
> -    'A/D/G/tau'      : Item(status='D '),
> -    'A/D/H'          : Item(status='D '),
> -    'A/D/H/chi'      : Item(status='D '),
> -    'A/D/H/psi'      : Item(status='D '),
> -    'A/D/H/omega'    : Item(status='D ')
>      })
> -  expected_status = svntest.wc.State(wc_dir, {
> +  expected_status = svntest.wc.State(other_wc, {
>      ''               : Item(status='  ', wc_rev=1),
>      'A'              : Item(status='  ', wc_rev=1),
>      'A/mu'           : Item(status='  ', wc_rev=1),
>      })
> -  expected_disk = svntest.wc.State(wc_dir, {
> +  expected_disk = svntest.wc.State('', {
>      'A'           : Item(contents=None),
>      'A/mu'        : Item(contents="This is the file 'mu'.\n")
>      })
> @@ -1971,20 +1951,15 @@ def fold_tree_with_unversioned_modified_
>  
>    # Fold the A dir to empty, expect the modified & unversioned ones left
>    # unversioned rather than removed, along with paths to those items.
> +
> +  # Even though the directory B and D is not deleted because of local
> +  # modificatoin or unversioned items, there will be only one notification at
> +  # B and D. 
>    expected_output = svntest.wc.State(wc_dir, {
> -    'A/B/lambda'     : Item(status='D '),
> -    'A/B/E'          : Item(status='D '),
> -    'A/B/E/alpha'    : Item(status='D '),
> -    'A/B/E/beta'     : Item(status='D '),
> -    'A/B/F'          : Item(status='D '),
> +    'A/B'            : Item(status='D '),
>      'A/C'            : Item(status='D '),
> -    'A/D/gamma'      : Item(status='D '),
> -    'A/D/G/rho'      : Item(status='D '),
> -    'A/D/G/tau'      : Item(status='D '),
> -    'A/D/H'          : Item(status='D '),
> -    'A/D/H/chi'      : Item(status='D '),
> -    'A/D/H/psi'      : Item(status='D '),
> -    'A/D/H/omega'    : Item(status='D ')
> +    'A/D'            : Item(status='D '),
> +    'A/mu'           : Item(status='D '),
>      })
>    # unversioned items will be ignored in in the status tree, since the
>    # run_and_verify_update() function uses a quiet version of svn status
> @@ -1994,8 +1969,8 @@ def fold_tree_with_unversioned_modified_
>      'iota'           : Item(status='  ', wc_rev=1),
>      'A'              : Item(status='  ', wc_rev=1)
>      })
> -  expected_disk = svntest.wc.State(wc_dir, {
> -    'iota'           : Item(contents="this is iota\n"),
> +  expected_disk = svntest.wc.State('', {
> +    'iota'           : Item(contents="This is the file 'iota'.\n"),
>      'A'              : Item(contents=None),
>      'A/mu'           : Item(contents="mu modified\n"),
>      'A/B'            : Item(contents=None),
> @@ -2013,7 +1988,6 @@ def fold_tree_with_unversioned_modified_
>                                          '--set-depth', 'empty', A_path)
>    verify_depth(None, "empty", A_path)
>  
> -
>  def depth_empty_update_on_file(sbox):
>    "depth-empty update on a file doesn't break it"
>    sbox.build()
> @@ -2052,6 +2026,224 @@ def depth_empty_update_on_file(sbox):
>                                                 [], 'info', iota_path)
>  
>  
> +def excluded_path_update_operation(sbox):
> +  """make sure update handle svn_depth_exclude properly"""
> +
> +  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
> +                                                             infinity=True)
> +  A_path = os.path.join(wc_dir, 'A')
> +  B_path = os.path.join(A_path, 'B')
> +  L_path = os.path.join(A_path, 'L')
> +  E_path = os.path.join(B_path, 'E')
> +
> +  # Simply exclude a subtree
> +  expected_output = svntest.wc.State(wc_dir, {
> +    'A/B/E'            : Item(status='D '),
> +    })
> +  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
> +  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
> +  expected_disk = svntest.main.greek_state.copy()
> +  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
> +
> +  svntest.actions.run_and_verify_update(wc_dir,
> +                                        expected_output,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None,
> +                                        '--set-depth', 'exclude', E_path)
> +  # verify_depth exclude? not implemented yet
> +
> +  # crop path B to immediates, this just pull in A/B/E again
> +  expected_output = svntest.wc.State(wc_dir, {
> +    'A/B/E'            : Item(status='A '),
> +    })
> +  expected_status.add({
> +    'A/B/E'            : Item(status='  ', wc_rev=1)
> +    })
> +  expected_disk.add({
> +    'A/B/E'          : Item(contents=None),
> +    })
> +  svntest.actions.run_and_verify_update(wc_dir,
> +                                        expected_output,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None,
> +                                        '--set-depth', 'immediates', B_path)
> +  verify_depth(None, "immediates", B_path)
> +
> +  # Exclude A/B/E again
> +  svntest.actions.run_and_verify_svn(None, None, [],
> +                                     'up', '--set-depth', 'exclude', E_path)
> +
> +  # Exclude path B totally, in which contains an excluded subtree.
> +  expected_output = svntest.wc.State(wc_dir, {
> +    'A/B'            : Item(status='D '),
> +    })
> +  expected_status.remove('A/B/F', 'A/B/E', 'A/B/lambda', 'A/B');
> +  expected_disk.remove('A/B/F', 'A/B/E', 'A/B/lambda', 'A/B');
> +  svntest.actions.run_and_verify_update(wc_dir,
> +                                        expected_output,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None,
> +                                        '--set-depth', 'exclude', B_path)
> +
> +  # Explicitly pull in excluded path B.
> +  expected_output = svntest.wc.State(wc_dir, {
> +    'A/B'            : Item(status='A '),
> +    'A/B/lambda'     : Item(status='A '),
> +    'A/B/E'          : Item(status='A '),
> +    'A/B/E/alpha'    : Item(status='A '),
> +    'A/B/E/beta'     : Item(status='A '),
> +    'A/B/F'          : Item(status='A '),
> +    })
> +  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
> +  expected_disk = svntest.main.greek_state.copy()
> +  svntest.actions.run_and_verify_update(wc_dir,
> +                                        expected_output,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None,
> +                                        B_path)
> +
> +def excluded_path_misc_operation(sbox):
> +  """make sure other subcommands handle exclude"""
> +
> +  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
> +                                                             infinity=True)
> +  A_path = os.path.join(wc_dir, 'A')
> +  B_path = os.path.join(A_path, 'B')
> +  L_path = os.path.join(A_path, 'L')
> +  E_path = os.path.join(B_path, 'E')
> +  LE_path = os.path.join(L_path, 'E')
> +
> +  # Simply exclude a subtree
> +  expected_output = svntest.wc.State(wc_dir, {
> +    'A/B/E'            : Item(status='D '),
> +    })
> +  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
> +  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
> +  expected_disk = svntest.main.greek_state.copy()
> +  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
> +
> +  svntest.actions.run_and_verify_update(wc_dir,
> +                                        expected_output,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None,
> +                                        '--set-depth', 'exclude', E_path)
> +
> +  # copy A/B to A/L, excluded entry should be copied too
> +  expected_output = ['A         '+L_path+'\n']
> +  svntest.actions.run_and_verify_svn(None, expected_output, [],
> +                                     'cp', B_path, L_path)
> +  # verify_depth exclude? not implemented yet
> +  #verify_depth(None, "empty", LE_path)
> +
> +  # revert A/L, with an excluded item in the tree
> +  expected_output = ["Reverted '"+L_path+"'\n"]
> +  svntest.actions.run_and_verify_svn(None, expected_output, [],
> +                                     'revert', '--depth=infinity', L_path)
> +
> +  # Get rid of A/L.
> +  svntest.actions.run_and_verify_svn(None, None, [],
> +                                     'rm', '--force', L_path)
> +
> +  # copy A/B to A/L again, excluded entry should be copied too
> +  expected_output = ['A         '+L_path+'\n']
> +  svntest.actions.run_and_verify_svn(None, expected_output, [],
> +                                     'cp', B_path, L_path)
> +
> +  # commit this copy, with an excluded item.
> +  expected_output = svntest.wc.State(wc_dir, { 'A/L' : Item(verb='Adding'), })
> +  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
> +  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
> +  expected_status.add({
> +    'A/L'        : Item(status='  ', wc_rev=2),
> +    'A/L/lambda' : Item(status='  ', wc_rev=2),
> +    'A/L/F'      : Item(status='  ', wc_rev=2),
> +    })
> +  svntest.actions.run_and_verify_commit(wc_dir, 
> +                                        expected_output,
> +                                        expected_status,
> +					None,
> +					wc_dir)
> +
> +  # Relocate wc, with excluded items in it.
> +  repo_dir = sbox.repo_dir
> +  repo_url = sbox.repo_url
> +  other_repo_dir, other_repo_url = sbox.add_repo_path('other')
> +  svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0)
> +  svntest.main.safe_rmtree(repo_dir, 1)
> +  svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate',
> +                                     repo_url, other_repo_url, wc_dir)
> +
> +  # remove the new directory A/L, with an excluded item.
> +  # If successed, no error will be thrown
> +  svntest.actions.run_and_verify_svn(None, None, [],
> +                                     'rm', L_path)
> +
> +  # revert the delete
> +  # If successed, no error will be thrown
> +  svntest.actions.run_and_verify_svn(None, None, [],
> +                                     'revert', '--depth=infinity', L_path)
> +
> +
> +def excluded_receive_remote_removal(sbox):
> +  """exclude flag should be cleared upon remote removal"""
> +  ign_a, ign_b, ign_c, wc \
> +         = set_up_depthy_working_copies(sbox, infinity=True)
> +
> +  A_path = os.path.join(wc, 'A')
> +  B_path = os.path.join(A_path, 'B')
> +  C_path = os.path.join(A_path, 'C')
> +
> +  # Exclude path B from wc
> +  expected_output = svntest.wc.State(wc, {
> +    'A/B'            : Item(status='D '),
> +    })
> +  expected_disk = svntest.main.greek_state.copy()
> +  expected_disk.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
> +                       'A/B/E', 'A/B/F', 'A/B')
> +  expected_status = svntest.actions.get_virginal_state(wc, 1)
> +  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
> +                         'A/B/E', 'A/B/F', 'A/B')
> +  svntest.actions.run_and_verify_update(wc,
> +                                        expected_output,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None,
> +                                        "--set-depth", "exclude", B_path)
> +
> +  # Remove path B in the repos.
> +  svntest.actions.run_and_verify_svn(None, None, [], "delete", "-m", 
> +                                     "Delete B.", sbox.repo_url + "/A/B")
> +
> +  # Update wc, should receive the removal of excluded path B 
> +  # and handle it silently.
> +  expected_status = svntest.actions.get_virginal_state(wc, 2)
> +  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
> +                         'A/B/E', 'A/B/F', 'A/B')
> +  svntest.actions.run_and_verify_update(wc,
> +                                        None,
> +                                        expected_disk,
> +                                        expected_status,
> +                                        None, None,
> +                                        None, None, None, None)
> +
> +  # Introduce a new path with the same name B.
> +  # This should succeed if the exclude entry is gone with the update,
> +  # otherwise a name conflict will rise up.
> +  expected_output = ['A         '+B_path+'\n']
> +  svntest.actions.run_and_verify_svn(None, expected_output, [],
> +                                     'cp', C_path, B_path)
> +
>  
>  #----------------------------------------------------------------------
>  # list all tests here, starting with None:
> @@ -2081,12 +2273,15 @@ test_list = [ None,
>                upgrade_from_above,
>                status_in_depthy_wc,
>                depthy_update_above_dir_to_be_deleted,
> -              XFail(depth_folding_clean_trees_1),
> -              XFail(depth_folding_clean_trees_2),
> -              XFail(depth_fold_expand_clean_trees),
> +              depth_folding_clean_trees_1,
> +              depth_folding_clean_trees_2,
> +              depth_fold_expand_clean_trees,
>                pull_in_tree_with_depth_option,
> -              XFail(fold_tree_with_unversioned_modified_items),
> +              fold_tree_with_unversioned_modified_items,
>                depth_empty_update_on_file,
> +              excluded_path_update_operation,
> +              excluded_path_misc_operation,
> +              excluded_receive_remote_removal,
>              ]
>  
>  if __name__ == "__main__":
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: svn-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: svn-help@subversion.tigris.org

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org