Index: subversion/include/svn_types.h
===================================================================
--- subversion/include/svn_types.h	(revision 24077)
+++ subversion/include/svn_types.h	(working copy)
@@ -212,8 +212,7 @@
     ### TODO(sd): This depth may turn out to be unnecessary. ### */
   svn_depth_unknown    = -2,
 
-  /* Exclude (remove, whatever) directory D.
-     ### TODO(sd): This depth may turn out to be unnecessary. ### */
+  /* Exclude (remove, whatever) directory D. */
   svn_depth_exclude    = -1,
 
   /* Just the named directory D, no entries.  Updates will not pull in
Index: subversion/libsvn_ra_svn/client.c
===================================================================
--- subversion/libsvn_ra_svn/client.c	(revision 24077)
+++ subversion/libsvn_ra_svn/client.c	(working copy)
@@ -1079,8 +1079,14 @@
 {
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
-  svn_boolean_t recurse = SVN_DEPTH_TO_RECURSE(depth);
+  svn_boolean_t recurse;
 
+  /* Old servers know "recursive" but not "depth"; help them DTRT. */
+  if (depth == svn_depth_empty || depth == svn_depth_files)
+    recurse = FALSE;
+  else
+    recurse = TRUE;
+
   /* Tell the server we want to start an update. */
   SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "update", "(?r)cbw", rev, target,
                                recurse, svn_depth_to_word(depth)));
Index: subversion/libsvn_wc/update_editor.c
===================================================================
--- subversion/libsvn_wc/update_editor.c	(revision 24077)
+++ subversion/libsvn_wc/update_editor.c	(working copy)
@@ -138,6 +138,9 @@
   /* The global edit baton. */
   struct edit_baton *edit_baton;
 
+  /* The depth of the directory in this edit. */
+  svn_depth_t depth;
+
   /* Baton for this directory's parent, or NULL if this is the root
      directory. */
   struct dir_baton *parent_baton;
@@ -567,7 +570,9 @@
   /* Set if this file is new. */
   svn_boolean_t added;
 
-  /* Set if this file is skipped because it was in conflict. */
+  /* Set if this file is skipped because it was in conflict, or because
+     it was a child of a directory at svn_depth_empty or
+     svn_depth_exclude. */
   svn_boolean_t skipped;
 
   /* Set if an unversioned file of the same name already existed in
@@ -701,7 +706,6 @@
 
 
 /* Prepare directory for dir_baton DB for updating or checking out.
- * Give it depth DEPTH.
  *
  * If the path already exists, but is not a working copy for
  * ANCESTOR_URL and ANCESTOR_REVISION, then an error will be returned. 
@@ -710,7 +714,6 @@
 prep_directory(struct dir_baton *db,
                const char *ancestor_url,
                svn_revnum_t ancestor_revision,
-               svn_depth_t depth,
                apr_pool_t *pool)
 {
   const char *repos;
@@ -730,7 +733,7 @@
      or by checking that it is so already. */
   SVN_ERR(svn_wc_ensure_adm3(db->path, NULL,
                              ancestor_url, repos,
-                             ancestor_revision, depth, pool));
+                             ancestor_revision, db->depth, pool));
 
   if (! db->edit_baton->adm_access
       || strcmp(svn_wc_adm_access_path(db->edit_baton->adm_access),
@@ -898,6 +901,7 @@
   eb->root_opened = TRUE;
 
   *dir_baton = d = make_dir_baton(NULL, eb, NULL, FALSE, pool);
+  d->depth = eb->depth;
   if (! *eb->target)
     {
       /* For an update with a NULL target, this is equivalent to open_dir(): */
@@ -1108,6 +1112,24 @@
              apr_pool_t *pool)
 {
   struct dir_baton *pb = parent_baton;
+
+  if (pb->depth == svn_depth_exclude)
+    return SVN_NO_ERROR;
+
+  /* For svn_depth_empty and svn_depth_files, ignore deletions of entries
+     that haven't been explicitly brought in. */
+  else if (pb->depth == svn_depth_empty || pb->depth == svn_depth_files)
+    {
+      svn_wc_adm_access_t *adm_access;
+      svn_wc_entry_t *entry;
+      const char *full_path = svn_path_join(pb->edit_baton->anchor, path, pool);
+      
+      SVN_ERR(svn_wc_entry(&entry, full_path,
+                           pb->edit_baton->adm_access, FALSE, pool));
+      if (! entry)
+        return SVN_NO_ERROR;
+    }
+
   return do_entry_deletion(pb->edit_baton, pb->path, path, &pb->log_number,
                            pool);
 }
@@ -1135,6 +1157,26 @@
       || ((! copyfrom_path) && (SVN_IS_VALID_REVNUM(copyfrom_revision))))
     abort();
 
+  *child_baton = db;
+
+  /* If we have a non-empty target and the parent of the newly added
+     directory is the root of the edit, then the new directory *is* the
+     target and we should set its depth accordingly. */
+  if (*eb->target && ! pb->parent_baton)
+    db->depth = eb->depth;
+  else if (pb->depth == svn_depth_empty
+           || pb->depth == svn_depth_exclude
+           || pb->depth == svn_depth_files)
+    {
+      db->depth = svn_depth_exclude;
+      db->bump_info->skipped = TRUE;
+      return SVN_NO_ERROR;
+    }
+  else if (pb->depth == svn_depth_immediates)
+    db->depth = svn_depth_empty;
+  else
+    db->depth = svn_depth_infinity;
+
   SVN_ERR(svn_io_check_path(db->path, &kind, db->pool));
 
   /* The path can exist, but it must be a directory... */
@@ -1287,23 +1329,10 @@
         }
     }
 
-  {
-    svn_depth_t depth = svn_depth_infinity;
+  SVN_ERR(prep_directory(db, db->new_URL,
+                         *(eb->target_revision),
+                         db->pool));
 
-    if (eb->depth == svn_depth_empty
-        || eb->depth == svn_depth_files
-        || eb->depth == svn_depth_immediates)
-      depth = svn_depth_empty;
-
-    SVN_ERR(prep_directory(db,
-                           db->new_URL,
-                           *(eb->target_revision),
-                           depth,
-                           db->pool));
-  }
-
-  *child_baton = db;
-
   /* If this add was obstructed by dir scheduled for addition without
      history let close_file() handle the notification because there
      might be properties to deal with. */
@@ -1350,6 +1379,26 @@
 
   /* Skip this directory if it has property conflicts. */
   SVN_ERR(svn_wc_entry(&entry, db->path, eb->adm_access, FALSE, pool));
+
+  /* If we have a non-empty target and the parent of the newly added
+     directory is the root of the edit, then the new directory *is* the
+     target and we should set its depth accordingly. */
+  if (*eb->target && ! pb->parent_baton)
+    db->depth = eb->depth;
+  else if (pb->depth == svn_depth_empty
+           || pb->depth == svn_depth_files
+           || pb->depth == svn_depth_exclude)
+    {
+      db->depth = svn_depth_exclude;
+      db->bump_info->skipped = TRUE;
+      return SVN_NO_ERROR;
+    }
+  else if (pb->depth == svn_depth_immediates)
+    db->depth = svn_depth_empty;
+  else if (entry)
+    /* Allow the entry's actual depth to override svn_depth_infinity. */
+    db->depth = entry->depth;
+
   if (entry)
     {
       /* Text conflicts can't happen for a directory, but we need to supply
@@ -1411,7 +1460,7 @@
   svn_prop_t *propchange;
   struct dir_baton *db = dir_baton;
 
-  if (db->bump_info->skipped)
+  if (db->bump_info->skipped || db->depth == svn_depth_exclude)
     return SVN_NO_ERROR;
 
   propchange = apr_array_push(db->propchanges);
@@ -1451,6 +1500,12 @@
   apr_array_header_t *entry_props, *wc_props, *regular_props;
   svn_wc_adm_access_t *adm_access;
       
+  if (db->depth == svn_depth_exclude)
+    {
+      SVN_ERR(maybe_bump_dir_info(db->edit_baton, db->bump_info, db->pool));
+      return SVN_NO_ERROR;
+    }
+
   SVN_ERR(svn_categorize_props(db->propchanges, &entry_props, &wc_props,
                                &regular_props, pool));
 
@@ -1578,6 +1633,11 @@
   const svn_wc_entry_t *ent;
   svn_wc_entry_t tmp_entry;
 
+  if (pb->depth == svn_depth_empty 
+      || pb->depth == svn_depth_exclude
+      || (kind == svn_node_dir && pb->depth == svn_depth_files))
+      return SVN_NO_ERROR;
+
   /* Extra check: an item by this name may not exist, but there may
      still be one scheduled for addition.  That's a genuine
      tree-conflict.  */
@@ -1663,8 +1723,14 @@
      conflict in the entry and proceed.  Similarly if it has changed
      kind.  see issuezilla task #398. */
 
-  fb = make_file_baton(pb, path, adding, pool);
+  *file_baton = fb = make_file_baton(pb, path, adding, pool);
 
+  if (pb->depth == svn_depth_empty || pb->depth == svn_depth_exclude)
+    {
+      fb->skipped = TRUE;
+      return SVN_NO_ERROR;
+    }
+
   /* It is interesting to note: everything below is just validation. We
      aren't actually doing any "work" or fetching any persistent data. */
 
@@ -1773,7 +1839,6 @@
 
   svn_pool_destroy(subpool);
 
-  *file_baton = fb;
   return SVN_NO_ERROR;
 }
 
