You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/09/21 16:14:14 UTC

svn commit: r999427 [2/3] - in /subversion/branches/atomic-revprop: ./ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/tigris/subversion/javahl/ subversion/bindings/java...

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c Tue Sep 21 14:14:12 2010
@@ -224,12 +224,6 @@ struct edit_baton
   svn_wc_conflict_resolver_func_t conflict_func;
   void *conflict_baton;
 
-  /* If the server sends add_file(copyfrom=...) and we don't have the
-     copyfrom file in the working copy, we use this callback to fetch
-     it directly from the repository. */
-  svn_wc_get_file_t fetch_func;
-  void *fetch_baton;
-
   /* Subtrees that were skipped during the edit, and therefore shouldn't
      have their revision/url info updated at the end.  If a path is a
      directory, its descendants will also be skipped.  The keys are absolute
@@ -1969,7 +1963,6 @@ do_entry_deletion(struct edit_baton *eb,
   svn_boolean_t conflicted;
   svn_wc_conflict_description2_t *tree_conflict = NULL;
   const char *dir_abspath = svn_dirent_dirname(local_abspath, pool);
-  svn_boolean_t hidden;
   svn_skel_t *work_item;
 
   SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
@@ -2153,7 +2146,7 @@ static svn_error_t *
 add_directory(const char *path,
               void *parent_baton,
               const char *copyfrom_path,
-              svn_revnum_t copyfrom_revision,
+              svn_revnum_t copyfrom_rev,
               apr_pool_t *pool,
               void **child_baton)
 {
@@ -2168,42 +2161,7 @@ add_directory(const char *path,
   svn_wc_conflict_description2_t *tree_conflict = NULL;
   svn_error_t *err;
 
-  /* Semantic check.  Either both "copyfrom" args are valid, or they're
-     NULL and SVN_INVALID_REVNUM.  A mixture is illegal semantics. */
-  SVN_ERR_ASSERT((copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_revision))
-                 || (!copyfrom_path &&
-                     !SVN_IS_VALID_REVNUM(copyfrom_revision)));
-  if (copyfrom_path != NULL)
-    {
-      /* ### todo: for now, this editor doesn't know how to deal with
-         copyfrom args.  Someday it will interpet them as an update
-         optimization, and actually copy one part of the wc to another.
-         Then it will recursively "normalize" all the ancestry in the
-         copied tree.  Someday!
-
-         Note from the future: if someday it does, we'll probably want
-         to tweak libsvn_ra_neon/fetch.c:validate_element() to accept
-         that an add-dir element can contain a delete-entry element
-         (because the dir might be added with history).  Currently
-         that combination will not validate.  See r30161, and see the
-         thread in which this message appears:
-
-      http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=136879
-      From: "David Glasser" <gl...@davidglasser.net>
-      To: "Karl Fogel" <kf...@red-bean.com>, dev@subversion.tigris.org
-      Cc: "Arfrever Frehtes Taifersar Arahesis" <ar...@gmail.com>,
-          glasser@tigris.org
-      Subject: Re: svn commit: r30161 - in trunk/subversion: \
-               libsvn_ra_neon tests/cmdline
-      Date: Fri, 4 Apr 2008 14:47:06 -0700
-      Message-ID: <1e...@mail.gmail.com>
-
-      */
-      return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                               _("Failed to add directory '%s': "
-                                 "copyfrom arguments not yet supported"),
-                               svn_dirent_local_style(path, pool));
-    }
+  SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
 
   SVN_ERR(make_dir_baton(&db, path, eb, pb, TRUE, pool));
   *child_baton = db;
@@ -2466,15 +2424,12 @@ add_directory(const char *path,
 
           /* If we are skipping an add, we need to tell the WC that
            * there's a node supposed to be here which we don't have. */
-          SVN_ERR(svn_wc__db_base_add_absent_node(eb->db, db->local_abspath,
+          SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
                                                   db->new_relpath,
                                                   eb->repos_root,
                                                   eb->repos_uuid,
-                                                  (eb->target_revision?
-                                                   *eb->target_revision
-                                                   : SVN_INVALID_REVNUM),
+                                                  *eb->target_revision,
                                                   svn_wc__db_kind_dir,
-                                                  svn_wc__db_status_not_present,
                                                   NULL, NULL, pool));
           SVN_ERR(remember_skipped_tree(eb, db->local_abspath));
 
@@ -3113,477 +3068,6 @@ absent_directory(const char *path,
 }
 
 
-/* Beginning at DIR_ABSPATH within a working copy, search the working copy
-   copy for a pre-existing versioned file which is exactly equal to
-   COPYFROM_PATH@COPYFROM_REV.
-
-   The current implementation does this by taking the repos_relpath of
-   dir_abspath and copyfrom_relpath to calculate where in the working copy
-   repos_relpath would be and then tries to confirm its guess.
-
-   1) When it finds a copied file there, it looks for its origin to see
-   if the origin matches the copied file good enough to use it as new base
-   contents and properties. If that is the case set NEW_BASE_CONTENTS
-   and NEW_BASE_PROPS to the found restult.
-
-   If the new base information is found check if the node is tree-conflicted,
-   and when that is the case use its in-wc contents and actual properties
-   to set NEW_CONTENTS and NEW_PROPS.
-
-   (If new base info is found, return)
-
-   2) If the node's BASE information matches the expected origin matches the the
-   copy origin good enough use it as NEW_BASE_CONTENTS and NEW_BASE_PROPS.
-
-   If the new base information is found and the db_status of the node is normal,
-   then set NEW_CONTENTS and NEW_PROPS with the found values.
-
-   If data is not found, its values will be set to NULL. 
-
-   Allocate the return values in RESULT_POOL, but perform all temporary allocations
-   in SCRATCH_POOL.
-
-   ### With a centralized datastore this becomes much easier. For now we
-   ### keep the old algorithm because the result is also used for copying
-   ### local changes. This support can probably be removed once we have real
-   ### local file moves.
-*/
-static svn_error_t *
-locate_copyfrom(svn_stream_t **new_base_contents,
-                svn_stream_t **new_contents,
-                apr_hash_t **new_base_props,
-                apr_hash_t **new_props,
-                svn_wc__db_t *db,
-                const char *dir_abspath,
-                const char *copyfrom_relpath,
-                svn_revnum_t copyfrom_rev,
-                apr_pool_t *result_pool,
-                apr_pool_t *scratch_pool)
-{
-  const char *ancestor_abspath, *ancestor_relpath;
-  const char *dir_repos_relpath, *dir_repos_root_url, *dir_repos_uuid;
-  const char *repos_relpath, *repos_root_url, *repos_uuid;
-  const char *local_abspath;
-
-  apr_size_t levels_up;
-  svn_error_t *err;
-
-  SVN_ERR_ASSERT(copyfrom_relpath[0] != '/');
-
-  SVN_ERR(svn_wc__db_scan_base_repos(&dir_repos_relpath, &dir_repos_root_url,
-                                     &dir_repos_uuid,
-                                     db, dir_abspath,
-                                     scratch_pool, scratch_pool));
-
-  /* Be pessimistic.  This function is basically a series of tests
-     that gives dozens of ways to fail our search, returning
-     SVN_NO_ERROR in each case.  If we make it all the way to the
-     bottom, we have a real discovery to return. */
-  *new_base_contents = NULL;
-  *new_contents = NULL;
-  *new_base_props = NULL;
-  *new_props = NULL;
-
-  /* Subtract the dest_dir's URL from the repository "root" URL to get
-     the absolute FS path represented by dest_dir. */
-
-  /* Find nearest FS ancestor dir of current FS path and copyfrom_parent */
-  ancestor_relpath = svn_relpath_get_longest_ancestor(dir_repos_relpath,
-                                                      copyfrom_relpath,
-                                                      scratch_pool);
-
-  /* Move 'up' the working copy to what ought to be the common ancestor dir. */
-  levels_up = svn_path_component_count(dir_repos_relpath)
-              - svn_path_component_count(ancestor_relpath);
-
-  /* Walk up the path dirent safe */
-  ancestor_abspath = dir_abspath;
-  while (levels_up-- > 0)
-    ancestor_abspath = svn_dirent_dirname(ancestor_abspath, scratch_pool);
-
-  /* Verify hypothetical ancestor */
-  err = svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
-                                   &repos_uuid,
-                                   db, ancestor_abspath,
-                                   scratch_pool, scratch_pool);
-
-  if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY) ||
-              (err->apr_err == SVN_ERR_WC_PATH_FOUND)))
-    {
-      svn_error_clear(err);
-      return SVN_NO_ERROR;
-    }
-  else
-    SVN_ERR(err);
-
-  /* If we got this far, we know that the ancestor dir exists, and
-     that it's a working copy too.  But is it from the same
-     repository?  And does it represent the URL we expect it to? */
-  if ((strcmp(dir_repos_uuid, repos_uuid) != 0)
-      || (strcmp(dir_repos_root_url, repos_root_url) != 0)
-      || (strcmp(ancestor_relpath, repos_relpath) != 0))
-    return SVN_NO_ERROR;
-
-  /* Add the remaining components to cwd, then add the remaining relpath to
-     where we hope the copyfrom_relpath file exists. */
-  local_abspath = svn_dirent_join(ancestor_abspath,
-                                 svn_dirent_skip_ancestor(ancestor_relpath,
-                                                          copyfrom_relpath),
-                                 scratch_pool);
-
-  /* Verify file in expected location */
-  {
-    svn_revnum_t rev, changed_rev;
-    svn_wc__db_status_t status, base_status;
-    svn_boolean_t conflicted, have_base;
-    const svn_checksum_t *checksum;
-
-    err = svn_wc__db_read_info(&status, NULL, &rev, &repos_relpath,
-                               &repos_root_url, &repos_uuid, &changed_rev,
-                               NULL, NULL, NULL, NULL, &checksum, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, &have_base,
-                               NULL, &conflicted, NULL,
-                               db, local_abspath, scratch_pool, scratch_pool);
-
-    if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY ||
-                (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND))))
-      {
-        svn_error_clear(err);
-        return SVN_NO_ERROR;
-      }
-    else
-      SVN_ERR(err);
-
-    /* Check if we have an added node with the right copyfrom information, as
-       this is what you would see on a file move. */
-       
-    if (status == svn_wc__db_status_added)
-      {
-        const char *op_root_abspath;
-        const char *original_repos_relpath, *original_root_url;
-        const char *original_uuid;
-        svn_revnum_t original_rev;
-
-        SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath,
-                                         &repos_relpath, &repos_root_url,
-                                         &repos_uuid, &original_repos_relpath,
-                                         &original_root_url, &original_uuid,
-                                         &original_rev,
-                                         db, local_abspath,
-                                         scratch_pool, scratch_pool));
-
-        if (status == svn_wc__db_status_copied
-            || status == svn_wc__db_status_moved_here)
-          {
-            original_repos_relpath = svn_relpath_join(
-                                    original_repos_relpath,
-                                    svn_dirent_skip_ancestor(op_root_abspath,
-                                                             local_abspath),
-                                    scratch_pool);
-
-            /* If the repository location matches our exact guess and
-               the file's recorded revisions tell us that the file had the
-               same contents at the copyfrom_revision, we can use this
-               data as new_base */
-            if (strcmp(original_repos_relpath, copyfrom_relpath) == 0
-                && strcmp(original_root_url, dir_repos_root_url) == 0
-                && strcmp(original_uuid, dir_repos_uuid) == 0
-                && strcmp(repos_relpath, copyfrom_relpath) == 0
-                && strcmp(repos_root_url, dir_repos_root_url) == 0
-                && strcmp(repos_uuid, dir_repos_uuid) == 0
-
-                && SVN_IS_VALID_REVNUM(changed_rev)
-                && changed_rev <= copyfrom_rev
-                && copyfrom_rev <= original_rev)
-              {
-                svn_node_kind_t kind;
-                svn_boolean_t text_changed;
-
-                /* WORKING_NODE has the right new-BASE information,
-                   so we have at least a partial result. */
-                SVN_ERR(svn_wc__db_pristine_read(new_base_contents,
-                                                 db, local_abspath, checksum,
-                                                 result_pool, scratch_pool));
-                SVN_ERR(svn_wc__get_pristine_props(new_base_props,
-                                                   db, local_abspath,
-                                                   result_pool, scratch_pool));
-
-                /* If the node is conflicted, that might have happened because
-                   the node was deleted. Which might indicate that we have
-                   a file move. In this case we like the real file data */
-                if (!conflicted
-                    && status == svn_wc__db_status_copied)
-                  return SVN_NO_ERROR; /* A local copy is no local modification
-                                          that we should keep */
-
-                /* ### TODO: Add verification to check that the conflict
-                       tells us that this is the right thing to do.
-
-                   ### Pre 1.7 we just assumed that it is ok without checking for
-                       conflicts, so this is not a regression */
-
-                SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
-
-                if (kind != svn_node_file)
-                  return SVN_NO_ERROR; /* Nothing to copy */
-
-                SVN_ERR(svn_wc__internal_text_modified_p(&text_changed, db,
-                                                         local_abspath, FALSE,
-                                                         TRUE, scratch_pool));
-
-                if (!text_changed)
-                  return SVN_NO_ERROR; /* Take the easy route */
-
-                SVN_ERR(svn_stream_open_readonly(new_contents, local_abspath,
-                                                 result_pool, scratch_pool));
-
-                SVN_ERR(svn_wc__get_actual_props(new_props, db, local_abspath,
-                                                 result_pool, scratch_pool));
-
-                return SVN_NO_ERROR;
-              }
-          }
-      }
-
-    if (!have_base)
-      return SVN_NO_ERROR;
-
-    base_status = status;
-
-    if (status != svn_wc__db_status_normal)
-      SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &rev,
-                                       &repos_relpath, &repos_root_url,
-                                       &repos_uuid, &changed_rev, NULL,
-                                       NULL, NULL, NULL, &checksum, NULL,
-                                       NULL, NULL,
-                                       db, local_abspath,
-                                       scratch_pool, scratch_pool));
-
-    if (base_status != svn_wc__db_status_normal)
-      return SVN_NO_ERROR; /* No interesting BASE_NODE */
-
-    if (!repos_relpath || !repos_root_url || !repos_uuid)
-      SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
-                                         &repos_uuid,
-                                         db, local_abspath,
-                                         scratch_pool, scratch_pool));
-
-    /* Is it from the same repository */
-    if ((strcmp(dir_repos_uuid, repos_uuid) != 0)
-        || (strcmp(dir_repos_root_url, repos_root_url) != 0)
-        || (strcmp(copyfrom_relpath, repos_relpath) != 0))
-      return SVN_NO_ERROR;
-
-    /* Ok, we know that we look at the right node, but do we have the
-       right revision?
-
-       To be sure that the base node has the right properties and text,
-       the node must be the same in copyfrom_rev and changed_rev, which
-       is only true within this specific range
-       */
-    if (!(SVN_IS_VALID_REVNUM(changed_rev)
-          && changed_rev <= copyfrom_rev
-          && copyfrom_rev <= rev))
-      {
-        return SVN_NO_ERROR;
-      }
-
-    /* BASE_NODE has the right new-BASE information,
-       so we have at least a partial result. */
-    SVN_ERR(svn_wc__db_pristine_read(new_base_contents,
-                                     db, local_abspath, checksum,
-                                     result_pool, scratch_pool));
-
-    SVN_ERR(svn_wc__db_base_get_props(new_base_props,
-                                      db, local_abspath, result_pool,
-                                      scratch_pool));
-
-    /* If the node is in status normal, the user probably intended to make
-       a copy of this in-wc node, so copy its local changes over to
-       the new file. */
-    if (status == svn_wc__db_status_normal)
-      {
-        svn_node_kind_t kind;
-        svn_boolean_t text_changed;
-
-        SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
-
-        if (kind != svn_node_file)
-          return SVN_NO_ERROR; /* Nothing to copy */
-
-        SVN_ERR(svn_wc__internal_text_modified_p(&text_changed, db,
-                                                 local_abspath, FALSE,
-                                                 TRUE, scratch_pool));
-
-        if (!text_changed)
-            return SVN_NO_ERROR; /* Take the easy route */
-
-        SVN_ERR(svn_stream_open_readonly(new_contents, local_abspath,
-                                         result_pool, scratch_pool));
-
-        SVN_ERR(svn_wc__get_actual_props(new_props, db, local_abspath,
-                                         result_pool, scratch_pool));
-      }
-  }
-  return SVN_NO_ERROR;
-}
-
-
-/* Given a set of properties PROPS_IN, find all regular properties
-   and shallowly copy them into a new set (allocate the new set in
-   POOL, but the set's members retain their original allocations). */
-static apr_hash_t *
-copy_regular_props(apr_hash_t *props_in,
-                   apr_pool_t *pool)
-{
-  apr_hash_t *props_out = apr_hash_make(pool);
-  apr_hash_index_t *hi;
-
-  for (hi = apr_hash_first(pool, props_in); hi; hi = apr_hash_next(hi))
-    {
-      const char *propname = svn__apr_hash_index_key(hi);
-      const svn_string_t *propval = svn__apr_hash_index_val(hi);
-
-      if (svn_wc_is_normal_prop(propname))
-        apr_hash_set(props_out, propname, APR_HASH_KEY_STRING, propval);
-    }
-  return props_out;
-}
-
-
-/* Do the "with history" part of add_file().
-
-   Attempt to locate COPYFROM_PATH@COPYFROM_REV within the existing working
-   copy.  If a node with such a base is found, copy the base *and working*
-   text and properties from there.  If not found, fetch the text and
-   properties from the repository by calling PB->edit_baton->fetch_func.
-
-   Store the copied base and working text in new temporary files in the adm
-   tmp area of the parent directory, whose baton is PB.  Set
-   TFB->copied_text_base_* and TFB->copied_working_text to their paths and
-   checksums.  Set TFB->copied_*_props to the copied properties.
-
-   After this function returns, subsequent apply_textdelta() commands coming
-   from the server may further alter the file before it is installed.
-
-   Ensure the resulting text base is in the pristine store, and set
-   TFB->copied_text_base_* to its readable abspath and checksums.
-*/
-static svn_error_t *
-add_file_with_history(struct dir_baton *pb,
-                      const char *copyfrom_path,
-                      svn_revnum_t copyfrom_rev,
-                      struct file_baton *tfb,
-                      apr_pool_t *result_pool,
-                      apr_pool_t *scratch_pool)
-{
-  struct edit_baton *eb = pb->edit_baton;
-  svn_stream_t *copied_stream;
-  const char *copied_text_base_tmp_abspath;
-  svn_wc__db_t *db = eb->db;
-  svn_stream_t *new_base_contents, *new_contents;
-  apr_hash_t *new_base_props, *new_props;
-
-  SVN_ERR_ASSERT(copyfrom_path[0] == '/');
-
-  tfb->added_with_history = TRUE;
-
-  /* Attempt to locate the copyfrom_path in the working copy first. */
-  SVN_ERR(locate_copyfrom(&new_base_contents, &new_contents,
-                          &new_base_props, &new_props,
-                          db, pb->local_abspath,
-                          copyfrom_path+1, /* Create repos_relpath */
-                          copyfrom_rev, result_pool, scratch_pool));
-
-  /* Open the text base for writing (this will get us a temporary file).  */
-  SVN_ERR(svn_wc__open_writable_base(&copied_stream,
-                                     &copied_text_base_tmp_abspath,
-  /* Compute an MD5 checksum for the stream as we write stuff into it.
-     ### this is temporary. in many cases, we already *know* the checksum
-     ### since it is a copy. */
-                                     &tfb->copied_text_base_md5_checksum,
-                                     &tfb->copied_text_base_sha1_checksum,
-                                     db, pb->local_abspath,
-                                     result_pool, scratch_pool));
-
-  if (new_base_contents && new_base_props)
-    {
-      /* Copy the existing file's text-base over to the (temporary)
-         new text-base, where the file baton expects it to be.  Get
-         the text base and props from the usual place or from the
-         revert place, depending on scheduling. */
-      SVN_ERR(svn_stream_copy3(new_base_contents, copied_stream,
-                               eb->cancel_func, eb->cancel_baton,
-                               scratch_pool));
-
-      if (!new_props)
-        new_props = new_base_props;
-    }
-  else  /* Couldn't find a file to copy  */
-    {
-      /* Fall back to fetching it from the repository instead. */
-
-      if (! eb->fetch_func)
-        return svn_error_create(SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
-                                _("No fetch_func supplied to update_editor"));
-
-      /* Fetch the repository file's text-base and base-props;
-         svn_stream_close() automatically closes the text-base file for us. */
-
-      /* copyfrom_path is a absolute path, fetch_func requires a path relative
-         to the root of the repository so skip the first '/'. */
-      SVN_ERR(eb->fetch_func(eb->fetch_baton, copyfrom_path + 1, copyfrom_rev,
-                             copied_stream,
-                             NULL, &new_base_props, scratch_pool));
-      SVN_ERR(svn_stream_close(copied_stream));
-
-      /* Filter out wc-props */
-      /* ### Do we get new values as modification or should these really
-             be installed? */
-      new_base_props = svn_prop_hash_dup(copy_regular_props(new_base_props,
-                                                             scratch_pool),
-                                         result_pool);
-
-      new_props = new_base_props;
-    }
-
-  SVN_ERR(svn_wc__db_pristine_install(db, copied_text_base_tmp_abspath,
-                                      tfb->copied_text_base_sha1_checksum,
-                                      tfb->copied_text_base_md5_checksum,
-                                      scratch_pool));
-
-  tfb->copied_base_props = new_base_props;
-   /* ### Currently we always have to set this even though we don't have
-          a real copy, or update_tests.py 60 "add_moved_file_has_props" fails
-    */
-  tfb->copied_working_props = new_props;
-
-  if (new_contents)
-    {
-      /* If we copied an existing file over, we need to copy its
-         working text too, to preserve any local mods.  (We already
-         read its working *props* into tfb->copied_working_props.) */
-      const char *temp_dir_abspath;
-      svn_stream_t *tmp_contents;
-
-        /* Make a unique file name for the copied working text. */
-      SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath,
-                                             db, pb->local_abspath,
-                                             scratch_pool, scratch_pool));
-
-      SVN_ERR(svn_stream_open_unique(&tmp_contents, &tfb->copied_working_text,
-                                     temp_dir_abspath, svn_io_file_del_none,
-                                     result_pool, scratch_pool));
-
-      SVN_ERR(svn_stream_copy3(new_contents, tmp_contents, eb->cancel_func,
-                               eb->cancel_baton,
-                               scratch_pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
 /* An svn_delta_editor_t function. */
 static svn_error_t *
 add_file(const char *path,
@@ -3605,11 +3089,7 @@ add_file(const char *path,
   svn_wc_conflict_description2_t *tree_conflict = NULL;
   svn_error_t *err;
 
-  /* Semantic check.  Either both "copyfrom" args are valid, or they're
-     NULL and SVN_INVALID_REVNUM.  A mixture is illegal semantics. */
-  SVN_ERR_ASSERT((copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev))
-                 || (!copyfrom_path &&
-                     !SVN_IS_VALID_REVNUM(copyfrom_rev)));
+  SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
 
   SVN_ERR(make_file_baton(&fb, pb, path, TRUE, pool));
   *file_baton = fb;
@@ -3839,15 +3319,12 @@ add_file(const char *path,
 
           /* If we are skipping an add, we need to tell the WC that
            * there's a node supposed to be here which we don't have. */
-          SVN_ERR(svn_wc__db_base_add_absent_node(eb->db, fb->local_abspath,
+          SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, fb->local_abspath,
                                                   fb->new_relpath,
                                                   eb->repos_root,
                                                   eb->repos_uuid,
-                                                  (eb->target_revision?
-                                                   *eb->target_revision
-                                                   : SVN_INVALID_REVNUM),
+                                                  *eb->target_revision,
                                                   svn_wc__db_kind_file,
-                                                  svn_wc__db_status_not_present,
                                                   NULL, NULL, subpool));
           SVN_ERR(remember_skipped_tree(eb, fb->local_abspath));
 
@@ -3876,13 +3353,6 @@ add_file(const char *path,
                       svn_wc_notify_tree_conflict, subpool);
     }
 
-  /* Now, if this is an add with history, do the history part. */
-  if (copyfrom_path && !fb->skip_this)
-    {
-      SVN_ERR(add_file_with_history(pb, copyfrom_path, copyfrom_rev,
-                                    fb, pool, subpool));
-    }
-
   svn_pool_destroy(subpool);
 
   return SVN_NO_ERROR;
@@ -5577,8 +5047,6 @@ make_editor(svn_revnum_t *target_revisio
             void *conflict_baton,
             svn_wc_external_update_t external_func,
             void *external_baton,
-            svn_wc_get_file_t fetch_func,
-            void *fetch_baton,
             const char *diff3_cmd,
             const apr_array_header_t *preserved_exts,
             const svn_delta_editor_t **editor,
@@ -5653,8 +5121,6 @@ make_editor(svn_revnum_t *target_revisio
   eb->cancel_baton             = cancel_baton;
   eb->conflict_func            = conflict_func;
   eb->conflict_baton           = conflict_baton;
-  eb->fetch_func               = fetch_func;
-  eb->fetch_baton              = fetch_baton;
   eb->allow_unver_obstructions = allow_unver_obstructions;
   eb->skipped_trees            = apr_hash_make(edit_pool);
   eb->ext_patterns             = preserved_exts;
@@ -5724,8 +5190,6 @@ svn_wc_get_update_editor4(const svn_delt
                           svn_boolean_t allow_unver_obstructions,
                           const char *diff3_cmd,
                           const apr_array_header_t *preserved_exts,
-                          svn_wc_get_file_t fetch_func,
-                          void *fetch_baton,
                           svn_wc_conflict_resolver_func_t conflict_func,
                           void *conflict_baton,
                           svn_wc_external_update_t external_func,
@@ -5744,7 +5208,6 @@ svn_wc_get_update_editor4(const svn_delt
                      cancel_func, cancel_baton,
                      conflict_func, conflict_baton,
                      external_func, external_baton,
-                     fetch_func, fetch_baton,
                      diff3_cmd, preserved_exts, editor, edit_baton,
                      result_pool, scratch_pool);
 }
@@ -5763,8 +5226,6 @@ svn_wc_get_switch_editor4(const svn_delt
                           svn_boolean_t allow_unver_obstructions,
                           const char *diff3_cmd,
                           const apr_array_header_t *preserved_exts,
-                          svn_wc_get_file_t fetch_func,
-                          void *fetch_baton,
                           svn_wc_conflict_resolver_func_t conflict_func,
                           void *conflict_baton,
                           svn_wc_external_update_t external_func,
@@ -5786,7 +5247,6 @@ svn_wc_get_switch_editor4(const svn_delt
                      cancel_func, cancel_baton,
                      conflict_func, conflict_baton,
                      external_func, external_baton,
-                     fetch_func, fetch_baton,
                      diff3_cmd, preserved_exts,
                      editor, edit_baton,
                      result_pool, scratch_pool);
@@ -5909,11 +5369,10 @@ svn_wc__check_wc_root(svn_boolean_t *wc_
   svn_wc__db_status_t status;
   svn_wc__db_kind_t my_kind;
 
-  /* Go ahead and initialize our return value to the most common
-     (code-wise) values. */
   if (!kind)
     kind = &my_kind;
 
+  /* Initialize our return values to the most common (code-wise) values. */
   *wc_root = TRUE;
   if (switched)
     *switched = FALSE;

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql Tue Sep 21 14:14:12 2010
@@ -384,8 +384,8 @@ CREATE TABLE WORKING_NODE (
   parent_relpath  TEXT,
 
   /* Is this node "present" or has it been excluded for some reason?
-     Only allowed values: normal, not-present, incomplete, base-deleted.
-     (the others do not make sense for the WORKING tree)
+     Only allowed values: normal, not-present, incomplete, base-deleted,
+     excluded.  (the others do not make sense for the WORKING tree)
 
      normal: this node has been added/copied/moved-here. There may be an
        underlying BASE node at this location, implying this is a replace.
@@ -407,7 +407,11 @@ CREATE TABLE WORKING_NODE (
 
      base-deleted: the underlying BASE node has been marked for deletion due
        to a delete or a move-away (see the moved_to column to determine
-       which), and has not been replaced.  */
+       which), and has not been replaced.
+
+     excluded: this node is administratively excluded (sparse WC). This must
+       be a child (or grandchild etc.) of a copied directory.
+  */
   presence  TEXT NOT NULL,
 
   /* the kind of the new node. may be "unknown" if the node is not present. */
@@ -732,8 +736,8 @@ CREATE TABLE NODES (
      In case 'op_depth' is greater than 0, this is part of a layer of
      working nodes; in that case, the following presence values apply:
 
-     Only allowed values: normal, not-present, incomplete, base-deleted.
-     (the others do not make sense for the WORKING tree)
+     Only allowed values: normal, not-present, incomplete, base-deleted,
+     excluded.  (the others do not make sense for the WORKING tree)
 
      normal: this node has been added/copied/moved-here. There may be an
        underlying BASE node at this location, implying this is a replace.
@@ -755,7 +759,11 @@ CREATE TABLE NODES (
 
      base-deleted: the underlying BASE node has been marked for deletion due
        to a delete or a move-away (see the moved_to column to determine
-       which), and has not been replaced.  */
+       which), and has not been replaced.
+
+     excluded: this node is administratively excluded (sparse WC). This must
+       be a child (or grandchild etc.) of a copied directory.
+  */
   presence  TEXT NOT NULL,
 
   /* NULL depth means "default" (typically svn_depth_infinity) */

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql Tue Sep 21 14:14:12 2010
@@ -68,6 +68,15 @@ select presence, kind, checksum, transla
 from working_node
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_SELECT_WORKING_NODE_1
+select presence, kind, checksum, translated_size,
+  changed_revision, changed_date, changed_author, depth, symlink_target,
+  repos_id, repos_path, revision,
+  moved_here, moved_to, last_mod_time, properties
+from nodes
+where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 order by op_depth desc
+limit 1;
+
 -- STMT_SELECT_ACTUAL_NODE
 select prop_reject, changelist, conflict_old, conflict_new,
 conflict_working, tree_conflict_data, properties
@@ -147,10 +156,19 @@ where wc_id = ?1 and local_relpath = ?2;
 select properties from base_node
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_SELECT_BASE_PROPS_1
+select properties from nodes
+where wc_id = ?1 and local_relpath = ?2 and op_depth = 0;
+
 -- STMT_SELECT_WORKING_PROPS
 SELECT properties, presence FROM WORKING_NODE
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_SELECT_WORKING_PROPS_1
+SELECT properties, presence FROM NODES
+WHERE wc_id = ?1 AND local_relpath = ?2
+AND op_depth > 0 ORDER BY op_depth DESC LIMIT 1;
+
 -- STMT_SELECT_ACTUAL_PROPS
 select properties from actual_node
 where wc_id = ?1 and local_relpath = ?2;
@@ -213,10 +231,6 @@ left outer join base_node on base_node.w
   and base_node.local_relpath = working_node.local_relpath
 where working_node.wc_id = ?1 and working_node.local_relpath = ?2;
 
--- STMT_SELECT_PARENT_STUB_INFO
-select presence = 'not-present', revnum from base_node
-where wc_id = ?1 and local_relpath = ?2;
-
 -- STMT_DELETE_LOCK
 delete from lock
 where repos_id = ?1 and repos_relpath = ?2;
@@ -620,11 +634,31 @@ UPDATE WORKING_NODE SET
   copyfrom_revnum = null
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_UPDATE_COPYFROM_TO_INHERIT_1
+UPDATE NODES SET
+  repos_id = null,
+  repos_path = null,
+  revision = null
+WHERE wc_id = ?1 AND local_relpath = ?2
+  AND op_depth IN (SELECT op_depth FROM nodes
+                   WHERE wc_id = ?1 AND local_relpath = ?2
+                   ORDER BY op_depth DESC
+                   LIMIT 1);
+
 -- STMT_DETERMINE_TREE_FOR_RECORDING
 SELECT 0 FROM BASE_NODE WHERE wc_id = ?1 AND local_relpath = ?2
 UNION
 SELECT 1 FROM WORKING_NODE WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_DETERMINE_TREE_FOR_RECORDING_1
+SELECT 0 FROM NODES WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0
+UNION
+SELECT 1 FROM NODES WHERE wc_id = ?1 AND local_relpath = ?2
+  AND op_depth IN (SELECT op_depth FROM nodes
+                   WHERE wc_id = ?1 AND local_relpath = ?2
+                   ORDER BY op_depth DESC
+                   LIMIT 1);
+
 
 /* ### Why can't this query not just use the BASE repository
    location values, instead of taking 3 additional parameters?! */

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.c Tue Sep 21 14:14:12 2010
@@ -404,7 +404,26 @@ assert_text_columns_equal(svn_sqlite__st
   return SVN_NO_ERROR;
 }
 
-#endif
+static svn_error_t *
+assert_blob_columns_equal(svn_sqlite__stmt_t *stmt1,
+                          svn_sqlite__stmt_t *stmt2,
+                          int column,
+                          apr_pool_t *scratch_pool)
+{
+  apr_size_t len1, len2;
+  const void *val1 = svn_sqlite__column_blob(stmt1, column, &len1, NULL);
+  const void *val2 = svn_sqlite__column_blob(stmt2, column, &len2, NULL);
+
+  if (!len1 && !len2)
+    return SVN_NO_ERROR;
+
+  if (len1 != len2 || memcmp(val1, val2, len1))
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                             "Blob of length %ld in statement 1 differs "
+                             "from blob of length %ld in statement 2",
+                             len1, len2);
+  return SVN_NO_ERROR;
+}
 
 static svn_error_t *
 assert_base_rows_match(svn_boolean_t have_row1,
@@ -455,14 +474,77 @@ assert_base_rows_match(svn_boolean_t hav
     SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 12)
                    == svn_sqlite__column_int64(stmt2, 12));
 
-    /* 14: verify props? */
+    /* verify props */
+    SVN_ERR(assert_blob_columns_equal(stmt1, stmt2, 13, scratch_pool));
   }
 
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+assert_working_rows_match(svn_boolean_t have_row1,
+                          svn_boolean_t have_row2,
+                          svn_sqlite__stmt_t *stmt1,
+                          svn_sqlite__stmt_t *stmt2,
+                          const char *relpath,
+                          apr_pool_t *scratch_pool)
+{
+  if (have_row1 != have_row2)
+    SVN_ERR(svn_error_createf(
+              SVN_ERR_WC_CORRUPT, NULL,
+              "Different results from WORKING (%d) and NODES queries (%d), "
+              "for local_relpath %s",
+              have_row1, have_row2, relpath));
+
+  if (!have_row1)
+    return SVN_NO_ERROR;
+
+  /* presence */
+  SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 0, scratch_pool));
+  /* kind */
+  SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 1, scratch_pool));
+  /* checksum */
+  SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 2, scratch_pool));
+  /* translated_size */
+  SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 3)
+                 == svn_sqlite__column_int64(stmt2, 3));
+  /* changed_rev */
+  SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 4)
+                 == svn_sqlite__column_int64(stmt2, 4));
+  /* changed_date */
+  SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 5)
+                 == svn_sqlite__column_int64(stmt2, 5));
+  /* changed_author */
+  SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 6, scratch_pool));
+  /* depth */
+  SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 7, scratch_pool));
+  /* symlink_target */
+  /* copyfrom_repos_id */
+  SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 9)
+                 == svn_sqlite__column_int64(stmt2, 9));
+  /* copyfrom_repos_path */
+  SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 7, scratch_pool));
+  /* copyfrom_revnum */
+  SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 11)
+                 == svn_sqlite__column_int64(stmt2, 11));
+  /* moved_here */
+  /* moved_to */
+  /* last_mod_time */
+  SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 14)
+                 == svn_sqlite__column_int64(stmt2, 14));
+  /* properties */
+#if 0
+  /* Disabled for now as base-deleted don't match */
+  SVN_ERR(assert_blob_columns_equal(stmt1, stmt2, 15, scratch_pool));
 #endif
 
+  return SVN_NO_ERROR;
+}
+
+#endif /* SVN_WC__NODES_ONLY */
+
+#endif /* SVN_WC__NODES */
+
 /* Scan from LOCAL_RELPATH upwards through parent nodes until we find a parent
    that has values in the 'repos_id' and 'repos_relpath' columns.  Return
    that information in REPOS_ID and REPOS_RELPATH (either may be NULL).
@@ -526,6 +608,10 @@ scan_upwards_for_repos(apr_int64_t *repo
                                      stmt, data_stmt,
                                      current_relpath,
                                      scratch_pool));
+      SVN_ERR(svn_sqlite__reset(data_stmt));
+#else
+      have_row = have_data_row;
+      stmt = data_stmt;
 #endif
 #endif
 
@@ -551,7 +637,6 @@ scan_upwards_for_repos(apr_int64_t *repo
             }
 
 #ifdef SVN_WC__NODES
-          SVN_ERR(svn_sqlite__reset(data_stmt));
 #endif
           return svn_error_compose_create(err, svn_sqlite__reset(stmt));
         }
@@ -572,14 +657,8 @@ scan_upwards_for_repos(apr_int64_t *repo
                                                                       NULL),
                                               relpath_suffix,
                                               result_pool);
-#ifdef SVN_WC__NODES
-          SVN_ERR(svn_sqlite__reset(data_stmt));
-#endif
           return svn_sqlite__reset(stmt);
         }
-#ifdef SVN_WC__NODES
-      SVN_ERR(svn_sqlite__reset(data_stmt));
-#endif
 #ifndef SVN_WC__NODES_ONLY
       SVN_ERR(svn_sqlite__reset(stmt));
 #endif
@@ -697,7 +776,9 @@ static svn_error_t *
 insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
 {
   const insert_base_baton_t *pibb = baton;
+#ifndef SVN_WC__NODES_ONLY
   svn_sqlite__stmt_t *stmt;
+#endif
 #ifdef SVN_WC__NODES
   svn_sqlite__stmt_t *stmt_node;
 #endif
@@ -757,7 +838,6 @@ insert_base_node(void *baton, svn_sqlite
 
 #ifdef SVN_WC__NODES
   SVN_ERR(svn_sqlite__get_statement(&stmt_node, sdb, STMT_INSERT_NODE));
-  { svn_revnum_t rev = pibb->changed_rev;
   SVN_ERR(svn_sqlite__bindf(stmt_node, "isisisr"
                             "tstr"               /* 8 - 11 */
                             "isnnnnns",          /* 12 - 19 */
@@ -772,12 +852,11 @@ insert_base_node(void *baton, svn_sqlite
                             (pibb->kind == svn_wc__db_kind_dir) ? /* 9 */
                                svn_depth_to_word(pibb->depth) : NULL,
                             kind_map, pibb->kind, /* 10 */
-                            rev,                  /* 11 */
+                            pibb->changed_rev,    /* 11 */
                             pibb->changed_date,   /* 12 */
                             pibb->changed_author, /* 13 */
                             (pibb->kind == svn_wc__db_kind_symlink) ?
                                 pibb->target : NULL)); /* 19 */
-  }
 
   if (pibb->kind == svn_wc__db_kind_file) {
     SVN_ERR(svn_sqlite__bind_checksum(stmt_node, 14, pibb->checksum,
@@ -955,7 +1034,9 @@ insert_working_node(void *baton,
 {
   const insert_working_baton_t *piwb = baton;
   const char *parent_relpath;
+#ifndef SVN_WC__NODES_ONLY
   svn_sqlite__stmt_t *stmt;
+#endif
 #ifdef SVN_WC__NODES
   svn_sqlite__stmt_t *stmt_node;
   apr_int64_t op_depth;
@@ -1376,15 +1457,34 @@ which_trees_exist(svn_boolean_t *base_ex
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
   *base_exists = FALSE;
   *working_exists = FALSE;
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_DETERMINE_TREE_FOR_RECORDING));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
-
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, sdb,
+                                    STMT_DETERMINE_TREE_FOR_RECORDING_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is", wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
+
   if (have_row)
     {
       int value = svn_sqlite__column_int(stmt, 0);
@@ -1932,18 +2032,18 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
 }
 
 
-svn_error_t *
-svn_wc__db_base_add_absent_node(svn_wc__db_t *db,
-                                const char *local_abspath,
-                                const char *repos_relpath,
-                                const char *repos_root_url,
-                                const char *repos_uuid,
-                                svn_revnum_t revision,
-                                svn_wc__db_kind_t kind,
-                                svn_wc__db_status_t status,
-                                const svn_skel_t *conflict,
-                                const svn_skel_t *work_items,
-                                apr_pool_t *scratch_pool)
+static svn_error_t *
+add_absent_excluded_not_present_node(svn_wc__db_t *db,
+                                     const char *local_abspath,
+                                     const char *repos_relpath,
+                                     const char *repos_root_url,
+                                     const char *repos_uuid,
+                                     svn_revnum_t revision,
+                                     svn_wc__db_kind_t kind,
+                                     svn_wc__db_status_t status,
+                                     const svn_skel_t *conflict,
+                                     const svn_skel_t *work_items,
+                                     apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
@@ -2002,6 +2102,46 @@ svn_wc__db_base_add_absent_node(svn_wc__
 
 
 svn_error_t *
+svn_wc__db_base_add_absent_node(svn_wc__db_t *db,
+                                const char *local_abspath,
+                                const char *repos_relpath,
+                                const char *repos_root_url,
+                                const char *repos_uuid,
+                                svn_revnum_t revision,
+                                svn_wc__db_kind_t kind,
+                                svn_wc__db_status_t status,
+                                const svn_skel_t *conflict,
+                                const svn_skel_t *work_items,
+                                apr_pool_t *scratch_pool)
+{
+  SVN_ERR_ASSERT(status == svn_wc__db_status_absent
+                 || status == svn_wc__db_status_excluded);
+
+  return add_absent_excluded_not_present_node(
+    db, local_abspath, repos_relpath, repos_root_url, repos_uuid, revision,
+    kind, status, conflict, work_items, scratch_pool);
+}
+
+
+svn_error_t *
+svn_wc__db_base_add_not_present_node(svn_wc__db_t *db,
+                                     const char *local_abspath,
+                                     const char *repos_relpath,
+                                     const char *repos_root_url,
+                                     const char *repos_uuid,
+                                     svn_revnum_t revision,
+                                     svn_wc__db_kind_t kind,
+                                     const svn_skel_t *conflict,
+                                     const svn_skel_t *work_items,
+                                     apr_pool_t *scratch_pool)
+{
+  return add_absent_excluded_not_present_node(
+    db, local_abspath, repos_relpath, repos_root_url, repos_uuid, revision,
+    kind, svn_wc__db_status_not_present, conflict, work_items, scratch_pool);
+}
+
+
+svn_error_t *
 svn_wc__db_base_remove(svn_wc__db_t *db,
                        const char *local_abspath,
                        apr_pool_t *scratch_pool)
@@ -2062,10 +2202,8 @@ svn_wc__db_base_get_info(svn_wc__db_stat
 {
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
-#ifndef SVN_WC__NODES_ONLY
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-#endif
 #ifdef SVN_WC__NODES
   svn_sqlite__stmt_t *stmt_nodes;
   svn_boolean_t have_node_row;
@@ -2095,10 +2233,17 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                             pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_node_row, stmt_nodes));
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(assert_base_rows_match(have_row, have_node_row, stmt, stmt_nodes,
                                  local_relpath, scratch_pool));
+#else
+  /* Lets assume the two queries return compatible data */
+  have_row = have_node_row;
+  stmt = stmt_nodes;
 #endif
 
+#endif /* SVN_WC__NODES */
+
   if (have_row)
     {
       svn_wc__db_kind_t node_kind = svn_sqlite__column_token(stmt, 3,
@@ -2229,8 +2374,10 @@ svn_wc__db_base_get_info(svn_wc__db_stat
     }
 
 #ifdef SVN_WC__NODES
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__reset(stmt_nodes));
 #endif
+#endif
 
   /* Note: given the composition, no need to wrap for tracing.  */
   return svn_error_compose_create(err, svn_sqlite__reset(stmt));
@@ -2362,10 +2509,29 @@ svn_wc__db_base_get_props(apr_hash_t **p
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   svn_error_t *err;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_node;
+  svn_boolean_t have_node_row;
+#endif
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
                                  STMT_SELECT_BASE_PROPS, scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(get_statement_for_path(&stmt_node, db, local_abspath,
+                                 STMT_SELECT_BASE_PROPS_1, scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_node_row, stmt_node));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR_ASSERT(have_row == have_node_row);
+  SVN_ERR(assert_blob_columns_equal(stmt, stmt_node, 0, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_node));
+#else
+  stmt = stmt_node;
+  have_row = have_node_row;
+#endif
+#endif
   if (!have_row)
     {
       err = svn_sqlite__reset(stmt);
@@ -4864,6 +5030,12 @@ svn_wc__db_read_info(svn_wc__db_status_t
   svn_boolean_t local_have_base;
   svn_boolean_t local_have_work;
   svn_boolean_t have_act;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes_base;
+  svn_sqlite__stmt_t *stmt_nodes_work;
+  svn_boolean_t local_have_nodes_base;
+  svn_boolean_t local_have_nodes_work;
+#endif
   svn_error_t *err = NULL;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -4897,6 +5069,39 @@ svn_wc__db_read_info(svn_wc__db_status_t
                             pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_act, stmt_act));
 
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes_base, pdh->wcroot->sdb,
+                                    lock ? STMT_SELECT_BASE_NODE_WITH_LOCK_1
+                                         : STMT_SELECT_BASE_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes_base, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&local_have_nodes_base, stmt_nodes_base));
+
+  /* Possible optimisation: if we didn't select op_depth > 0 then this
+     would give us the base node when there is no working node. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes_work, pdh->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes_work, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&local_have_nodes_work, stmt_nodes_work));
+
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_base_rows_match(*have_base, local_have_nodes_base,
+                                 stmt_base, stmt_nodes_base,
+                                 local_relpath, scratch_pool));
+  SVN_ERR(assert_working_rows_match(*have_work, local_have_nodes_work,
+                                    stmt_work, stmt_nodes_work,
+                                    local_relpath, scratch_pool));
+#else
+  /* Lets assume the queries return compatible data */
+  *have_base = local_have_nodes_base;
+  *have_work = local_have_nodes_work;
+  stmt_base = stmt_nodes_base;
+  stmt_work = stmt_nodes_work;
+#endif
+
+#endif /* SVN_WC__NODES */
+
   if (*have_base || *have_work)
     {
       svn_wc__db_kind_t node_kind;
@@ -5197,6 +5402,13 @@ svn_wc__db_read_info(svn_wc__db_status_t
                                                      scratch_pool));
     }
 
+#ifdef SVN_WC__NODES
+#ifndef SVN_WC__NODES_ONLY
+  err = svn_error_compose_create(err, svn_sqlite__reset(stmt_nodes_base));
+  err = svn_error_compose_create(err, svn_sqlite__reset(stmt_nodes_work));
+#endif
+#endif
+
   err = svn_error_compose_create(err, svn_sqlite__reset(stmt_base));
   err = svn_error_compose_create(err, svn_sqlite__reset(stmt_work));
   SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt_act)));
@@ -5298,10 +5510,34 @@ svn_wc__db_read_pristine_props(apr_hash_
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_node;
+  svn_boolean_t have_node_row;
+#endif
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
                                  STMT_SELECT_WORKING_PROPS, scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+  SVN_ERR(get_statement_for_path(&stmt_node, db, local_abspath,
+                                 STMT_SELECT_WORKING_PROPS_1, scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_node_row, stmt_node));
+
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR_ASSERT(have_row == have_node_row);
+#if 0
+  /* Disabled for now as base-deleted don't match */
+  SVN_ERR(assert_blob_columns_equal(stmt, stmt_node, 0, scratch_pool));
+#endif
+  SVN_ERR(svn_sqlite__reset(stmt_node));
+#else
+  stmt = stmt_node;
+  have_row = have_node_row;
+#endif
+#endif
 
   /* If there is a WORKING row, then examine its status:
 
@@ -7348,58 +7584,6 @@ svn_wc__db_temp_borrow_sdb(svn_sqlite__d
   return SVN_NO_ERROR;
 }
 
-
-svn_error_t *
-svn_wc__db_temp_is_dir_deleted(svn_boolean_t *not_present,
-                               svn_revnum_t *base_revision,
-                               svn_wc__db_t *db,
-                               const char *local_dir_abspath,
-                               apr_pool_t *scratch_pool)
-{
-  const char *parent_abspath;
-  const char *base_name;
-  svn_wc__db_pdh_t *pdh;
-  const char *local_relpath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
-  SVN_ERR_ASSERT(not_present != NULL);
-  SVN_ERR_ASSERT(base_revision != NULL);
-
-  svn_dirent_split(&parent_abspath, &base_name, local_dir_abspath,
-                   scratch_pool);
-
-  /* The parent should be a working copy if this function is called.
-     Basically, the child is in an "added" state, which is not possible
-     for a working copy root.  */
-  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
-                              parent_abspath, svn_sqlite__mode_readonly,
-                              scratch_pool, scratch_pool));
-  VERIFY_USABLE_PDH(pdh);
-
-  /* Build the local_relpath for the requested directory.  */
-  local_relpath = svn_dirent_join(local_relpath, base_name, scratch_pool);
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
-                                    STMT_SELECT_PARENT_STUB_INFO));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
-
-  /* There MAY be a BASE_NODE row in the parent directory. It is entirely
-     possible the parent only has WORKING_NODE rows. If there is no BASE_NODE,
-     then we certainly aren't looking at a 'not-present' row.  */
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
-  *not_present = have_row && svn_sqlite__column_int(stmt, 0);
-  if (*not_present)
-    {
-      *base_revision = svn_sqlite__column_revnum(stmt, 1);
-    }
-  /* else don't touch *BASE_REVISION.  */
-
-  return svn_error_return(svn_sqlite__reset(stmt));
-}
-
 svn_error_t *
 svn_wc__db_read_conflict_victims(const apr_array_header_t **victims,
                                  svn_wc__db_t *db,
@@ -8190,7 +8374,11 @@ svn_wc__db_temp_op_set_base_incomplete(s
   SVN_ERR(svn_sqlite__bind_text(stmt, 3, incomplete ? "incomplete" : "normal"));
   SVN_ERR(svn_sqlite__update(&affected_node_rows, stmt));
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR_ASSERT(affected_rows == affected_node_rows);
+#else
+  affected_rows = affected_node_rows;
+#endif
 #endif
 
   if (affected_rows > 0)
@@ -8495,7 +8683,8 @@ make_copy_txn(void *baton,
       SVN_ERR(svn_sqlite__bindf(stmt, "isi",
                                 mcb->pdh->wcroot->wc_id,
                                 mcb->local_relpath,
-                                (*mcb->local_relpath == '\0') ? 1 : 2));
+                                (*mcb->local_relpath == '\0'
+                                 ? (apr_int64_t)1 : (apr_int64_t)2)));
 
       SVN_ERR(svn_sqlite__step_done(stmt));
 #endif
@@ -8525,7 +8714,8 @@ make_copy_txn(void *baton,
       SVN_ERR(svn_sqlite__bindf(stmt, "isi",
                                 mcb->pdh->wcroot->wc_id,
                                 mcb->local_relpath,
-                                (*mcb->local_relpath == '\0') ? 1 : 2));
+                                (*mcb->local_relpath == '\0'
+                                 ? (apr_int64_t)1 : (apr_int64_t)2)));
 
       SVN_ERR(svn_sqlite__step_done(stmt));
 #endif
@@ -8687,6 +8877,10 @@ svn_wc__db_temp_elide_copyfrom(svn_wc__d
   const char *local_relpath;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_node;
+  svn_boolean_t have_node_row;
+#endif
   apr_int64_t original_repos_id;
   const char *original_repos_relpath;
   svn_revnum_t original_revision;
@@ -8706,10 +8900,29 @@ svn_wc__db_temp_elide_copyfrom(svn_wc__d
 
   /* Examine the current WORKING_NODE row's copyfrom information. If there
      is no WORKING node, then simply exit.  */
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_SELECT_WORKING_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_node, pdh->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_node, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_node_row, stmt_node));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_working_rows_match(have_row, have_node_row, stmt, stmt_node,
+                                    local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_node));
+#else
+  stmt = stmt_node;
+  have_row = have_node_row;
+#endif
+#endif
+
   if (!have_row)
     return svn_error_return(svn_sqlite__reset(stmt));
 
@@ -8759,10 +8972,22 @@ svn_wc__db_temp_elide_copyfrom(svn_wc__d
 
   /* The child's copyfrom information is derivable from the parent.
      The data should be reset to null, indicating the derivation.  */
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_UPDATE_COPYFROM_TO_INHERIT));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__update(NULL, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+  /* Should probably use the op_depth from query above and simplify this
+     query. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt_node, pdh->wcroot->sdb,
+                                    STMT_UPDATE_COPYFROM_TO_INHERIT_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_node, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__update(NULL, stmt_node));
+#endif
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc_db.h Tue Sep 21 14:14:12 2010
@@ -618,7 +618,6 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
 
      svn_wc__db_status_absent
      svn_wc__db_status_excluded
-     svn_wc__db_status_not_present
 
    If CONFLICT is not NULL, then it describes a conflict for this node. The
    node will be record as conflicted (in ACTUAL).
@@ -642,6 +641,36 @@ svn_wc__db_base_add_absent_node(svn_wc__
                                 apr_pool_t *scratch_pool);
 
 
+/* Create a node in the BASE tree that is present in name only.
+
+   The new node will be located at LOCAL_ABSPATH, and correspond to the
+   repository node described by <REPOS_RELPATH, REPOS_ROOT_URL, REPOS_UUID>
+   at revision REVISION.
+
+   The node's kind is described by KIND, and the reason for its absence
+   is 'svn_wc__db_status_not_present'.
+
+   If CONFLICT is not NULL, then it describes a conflict for this node. The
+   node will be record as conflicted (in ACTUAL).
+
+   Any work items that are necessary as part of this node construction may
+   be passed in WORK_ITEMS.
+
+   All temporary allocations will be made in SCRATCH_POOL.
+*/
+svn_error_t *
+svn_wc__db_base_add_not_present_node(svn_wc__db_t *db,
+                                     const char *local_abspath,
+                                     const char *repos_relpath,
+                                     const char *repos_root_url,
+                                     const char *repos_uuid,
+                                     svn_revnum_t revision,
+                                     svn_wc__db_kind_t kind,
+                                     const svn_skel_t *conflict,
+                                     const svn_skel_t *work_items,
+                                     apr_pool_t *scratch_pool);
+
+
 /* Remove a node from the BASE tree.
 
    The node to remove is indicated by LOCAL_ABSPATH from the local
@@ -2198,14 +2227,6 @@ svn_wc__db_temp_forget_directory(svn_wc_
                                  const char *local_dir_abspath,
                                  apr_pool_t *scratch_pool);
 
-
-svn_error_t *
-svn_wc__db_temp_is_dir_deleted(svn_boolean_t *not_present,
-                               svn_revnum_t *base_revision,
-                               svn_wc__db_t *db,
-                               const char *local_abspath,
-                               apr_pool_t *scratch_pool);
-
 /* Removes all references of LOCAL_ABSPATH from its working copy
    using DB. */
 svn_error_t *

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/workqueue.c Tue Sep 21 14:14:12 2010
@@ -687,16 +687,15 @@ run_base_remove(svn_wc__db_t *db,
 
   if (keep_not_present)
     {
-      SVN_ERR(svn_wc__db_base_add_absent_node(db, local_abspath,
-                                              repos_relpath,
-                                              repos_root_url,
-                                              repos_uuid,
-                                              revision,
-                                              kind,
-                                              svn_wc__db_status_not_present,
-                                              NULL,
-                                              NULL,
-                                              scratch_pool));
+      SVN_ERR(svn_wc__db_base_add_not_present_node(db, local_abspath,
+                                                   repos_relpath,
+                                                   repos_root_url,
+                                                   repos_uuid,
+                                                   revision,
+                                                   kind,
+                                                   NULL,
+                                                   NULL,
+                                                   scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -793,11 +792,10 @@ run_deletion_postcommit(svn_wc__db_t *db
              lie;  therefore, it must remember the file as being
              'deleted' for a while.  Create a new, uninteresting
              ghost entry:  */
-          SVN_ERR(svn_wc__db_base_add_absent_node(
+          SVN_ERR(svn_wc__db_base_add_not_present_node(
                     db, local_abspath,
                     repos_relpath, repos_root_url, repos_uuid,
                     new_revision, kind,
-                    svn_wc__db_status_not_present,
                     NULL, NULL,
                     scratch_pool));
         }

Modified: subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/atomic-revprop/subversion/mod_dav_svn/dav_svn.h Tue Sep 21 14:14:12 2010
@@ -645,12 +645,13 @@ dav_svn__get_deleted_rev_report(const da
 /*** posts/ ***/
 
 /* The list of Subversion's custom POSTs. */
-/* ### should move these report names to a public header to share with
-   ### the client (and third parties). */
+/* ### TODO:  Populate this list and transmit its contents in the
+   ### OPTIONS response.
 static const char * dav_svn__posts_list[] = {
   "create-txn",
   NULL
 };
+*/
 
 /* The various POST handlers, defined in posts/, and used by repos.c.  */
 dav_error *

Modified: subversion/branches/atomic-revprop/subversion/svn/upgrade-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/svn/upgrade-cmd.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/svn/upgrade-cmd.c (original)
+++ subversion/branches/atomic-revprop/subversion/svn/upgrade-cmd.c Tue Sep 21 14:14:12 2010
@@ -31,6 +31,7 @@
 #include "svn_client.h"
 #include "svn_error_codes.h"
 #include "svn_error.h"
+#include "svn_path.h"
 #include "cl.h"
 #include "svn_private_config.h"
 
@@ -59,6 +60,19 @@ svn_cl__upgrade(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
 
+  /* Don't even attempt to modify the working copy if any of the
+   * targets look like URLs. URLs are invalid input. */
+  for (i = 0; i < targets->nelts; i++)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+      if (svn_path_is_url(target))
+        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+                                                  NULL,
+                                                  _("'%s' is not a local path"),
+                                                  target));
+    }
+
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < targets->nelts; i++)
     {

Modified: subversion/branches/atomic-revprop/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/svnrdump/dump_editor.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/atomic-revprop/subversion/svnrdump/dump_editor.c Tue Sep 21 14:14:12 2010
@@ -33,6 +33,12 @@
 
 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
 
+#ifdef SVN_DEBUG
+#define LDR_DBG(x) SVN_DBG(x)
+#else
+#define LDR_DBG(x) while(0)
+#endif
+
 /* The baton used by the dump editor. */
 struct dump_edit_baton {
   /* The output stream we write the dumpfile to */
@@ -113,7 +119,7 @@ make_dir_baton(const char *path,
   new_db->copyfrom_rev = copyfrom_rev;
   new_db->added = added;
   new_db->written_out = FALSE;
-  new_db->deleted_entries = apr_hash_make(pool);
+  new_db->deleted_entries = apr_hash_make(eb->pool);
 
   return new_db;
 }
@@ -197,10 +203,10 @@ dump_node(struct dump_edit_baton *eb,
           apr_pool_t *pool)
 {
   /* Remove leading slashes from path and copyfrom_path */
-  if (path && strcmp(path, "/"))
+  if (path)
     path = ((*path == '/') ? path + 1 : path);
   
-  if (copyfrom_path && strcmp(copyfrom_path, "/"))
+  if (copyfrom_path)
     copyfrom_path = ((*copyfrom_path == '/') ?
                      copyfrom_path + 1 : copyfrom_path);
 
@@ -315,6 +321,7 @@ open_root(void *edit_baton,
   struct dump_edit_baton *eb = edit_baton;
   /* Allocate a special pool for the edit_baton to avoid pool
      lifetime issues */
+
   eb->pool = svn_pool_create(pool);
   eb->props = apr_hash_make(eb->pool);
   eb->deleted_props = apr_hash_make(eb->pool);
@@ -322,6 +329,8 @@ open_root(void *edit_baton,
 
   *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
                                edit_baton, NULL, FALSE, pool);
+  LDR_DBG(("open_root %p\n", *root_baton));
+
   return SVN_NO_ERROR;
 }
 
@@ -332,14 +341,15 @@ delete_entry(const char *path,
              apr_pool_t *pool)
 {
   struct dir_baton *pb = parent_baton;
-  const char *mypath = apr_pstrdup(pool, path);
+
+  LDR_DBG(("delete_entry %s\n", path));
 
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
 
   /* Add this path to the deleted_entries of the parent directory
      baton. */
-  apr_hash_set(pb->deleted_entries, mypath, APR_HASH_KEY_STRING, pb);
+  apr_hash_set(pb->deleted_entries, path, APR_HASH_KEY_STRING, pb);
 
   return SVN_NO_ERROR;
 }
@@ -358,6 +368,8 @@ add_directory(const char *path,
     = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb, TRUE, pool);
   svn_boolean_t is_copy;
 
+  LDR_DBG(("add_directory %s\n", path));
+
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
 
@@ -398,6 +410,8 @@ open_directory(const char *path,
   const char *copyfrom_path = NULL;
   svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
 
+  LDR_DBG(("open_directory %s\n", path));
+
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
 
@@ -423,14 +437,19 @@ close_directory(void *dir_baton,
 {
   struct dir_baton *db = dir_baton;
   struct dump_edit_baton *eb = db->eb;
+  apr_pool_t *iterpool;
   apr_hash_index_t *hi;
-  apr_pool_t *iterpool = svn_pool_create(pool);
+
+  LDR_DBG(("close_directory %p\n", dir_baton));
+
+  /* Create a pool just for iterations to allocate a loop variable */
+  iterpool = svn_pool_create(pool);
 
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(eb, &(eb->dump_props_pending), TRUE, pool));
 
-  /* Dump the directory entries */
-  for (hi = apr_hash_first(pool, db->deleted_entries); hi;
+  /* Dump the deleted directory entries */
+  for (hi = apr_hash_first(iterpool, db->deleted_entries); hi;
        hi = apr_hash_next(hi))
     {
       const void *key;
@@ -438,12 +457,11 @@ close_directory(void *dir_baton,
       apr_hash_this(hi, &key, NULL, NULL);
       path = key;
 
-      svn_pool_clear(iterpool);
-
       SVN_ERR(dump_node(db->eb, path, svn_node_unknown, svn_node_action_delete,
-                        FALSE, NULL, SVN_INVALID_REVNUM, iterpool));
+                        FALSE, NULL, SVN_INVALID_REVNUM, pool));
     }
 
+  svn_hash__clear(db->deleted_entries, pool);
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
@@ -460,6 +478,8 @@ add_file(const char *path,
   void *val;
   svn_boolean_t is_copy;
 
+  LDR_DBG(("add_file %s\n", path));
+
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
 
@@ -500,6 +520,8 @@ open_file(const char *path,
   const char *copyfrom_path = NULL;
   svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
 
+  LDR_DBG(("open_file %s\n", path));
+
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
 
@@ -530,6 +552,8 @@ change_dir_prop(void *parent_baton,
 {
   struct dir_baton *db = parent_baton;
 
+  LDR_DBG(("change_dir_prop %p\n", parent_baton));
+
   if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
     return SVN_NO_ERROR;
 
@@ -566,6 +590,8 @@ change_file_prop(void *file_baton,
 {
   struct dump_edit_baton *eb = file_baton;
 
+  LDR_DBG(("change_file_prop %p\n", file_baton));
+
   if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
     return SVN_NO_ERROR;
 
@@ -620,6 +646,8 @@ apply_textdelta(void *file_baton, const 
   hb->pool = handler_pool;
   hb->eb = eb;
 
+  LDR_DBG(("apply_textdelta %p\n", file_baton));
+
   /* Use a temporary file to measure the text-content-length */
   SVN_ERR(svn_stream_open_unique(&(hb->delta_filestream), &hb->delta_abspath,
                                  NULL, svn_io_file_del_none, hb->pool,
@@ -650,6 +678,8 @@ close_file(void *file_baton,
   svn_stream_t *delta_filestream;
   apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t));
 
+  LDR_DBG(("close_file %p\n", file_baton));
+
   /* Some pending properties to dump? */
   SVN_ERR(dump_props(eb, &(eb->dump_props_pending), FALSE, pool));
 
@@ -737,6 +767,7 @@ static svn_error_t *
 close_edit(void *edit_baton, apr_pool_t *pool)
 {
   struct dump_edit_baton *eb = edit_baton;
+  LDR_DBG(("close_edit\n"));
   svn_pool_destroy(eb->pool);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c Tue Sep 21 14:14:12 2010
@@ -30,9 +30,15 @@
 #include "svn_path.h"
 #include "svn_ra.h"
 #include "svn_io.h"
+#include "svn_private_config.h"
+
+#include <apr_network_io.h>
 
 #include "load_editor.h"
 
+#define SVNRDUMP_PROP_LOCK SVN_PROP_PREFIX "rdump-lock"
+#define LOCK_RETRIES 10
+
 #ifdef SVN_DEBUG
 #define LDR_DBG(x) SVN_DBG(x)
 #else
@@ -50,6 +56,66 @@ commit_callback(const svn_commit_info_t 
   return SVN_NO_ERROR;
 }
 
+/* Acquire a lock (of sorts) on the repository associated with the
+ * given RA SESSION. This lock is just a revprop change attempt in a
+ * time-delay loop. This function is duplicated by svnsync in main.c.
+ *
+ * ### TODO: Make this function more generic and
+ * expose it through a header for use by other Subversion
+ * applications to avoid duplication.
+ */
+static svn_error_t *
+get_lock(svn_ra_session_t *session, apr_pool_t *pool)
+{
+  char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
+  svn_string_t *mylocktoken, *reposlocktoken;
+  apr_status_t apr_err;
+  apr_pool_t *subpool;
+  int i;
+
+  apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
+
+  mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
+                                   svn_uuid_generate(pool));
+
+  subpool = svn_pool_create(pool);
+
+  for (i = 0; i < LOCK_RETRIES; ++i)
+    {
+      svn_pool_clear(subpool);
+
+      SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, &reposlocktoken,
+                              subpool));
+
+      if (reposlocktoken)
+        {
+          /* Did we get it? If so, we're done, otherwise we sleep. */
+          if (strcmp(reposlocktoken->data, mylocktoken->data) == 0)
+            return SVN_NO_ERROR;
+          else
+            {
+              SVN_ERR(svn_cmdline_printf
+                      (pool, _("Failed to get lock on destination "
+                               "repos, currently held by '%s'\n"),
+                       reposlocktoken->data));
+
+              apr_sleep(apr_time_from_sec(1));
+            }
+        }
+      else if (i < LOCK_RETRIES - 1)
+        {
+          /* Except in the very last iteration, try to set the lock. */
+          SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK,
+                                         mylocktoken, subpool));
+        }
+    }
+
+  return svn_error_createf(APR_EINVAL, NULL,
+                           _("Couldn't get lock on destination repos "
+                             "after %d attempts"), i);
+}
 
 static svn_error_t *
 new_revision_record(void **revision_baton,
@@ -539,13 +605,11 @@ drive_dumpstream_loader(svn_stream_t *st
   struct parse_baton *pb;
   pb = parse_baton;
 
-  /* ### TODO: Figure out if we're allowed to set revprops before
-     ### we're too late and mess up the repository. svnsync uses some
-     ### sort of locking mechanism. */
-
+  SVN_ERR(get_lock(session, pool));
   SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
   SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
                                       NULL, NULL, pool));
+  SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, NULL, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/atomic-revprop/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/svnserve/serve.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/svnserve/serve.c (original)
+++ subversion/branches/atomic-revprop/subversion/svnserve/serve.c Tue Sep 21 14:14:12 2010
@@ -1505,6 +1505,14 @@ static svn_error_t *get_dir(svn_ra_svn_c
           svn_pool_clear(subpool);
 
           file_path = svn_uri_join(full_path, name, subpool);
+
+          if (! lookup_access(subpool, b, conn, svn_authz_read,
+                              file_path, FALSE))
+            {
+              apr_hash_set(entries, name, APR_HASH_KEY_STRING, NULL);
+              continue;
+            }
+
           entry = apr_pcalloc(pool, sizeof(*entry));
 
           if (dirent_fields & SVN_DIRENT_KIND)

Modified: subversion/branches/atomic-revprop/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/svnsync/main.c?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/svnsync/main.c (original)
+++ subversion/branches/atomic-revprop/subversion/svnsync/main.c Tue Sep 21 14:14:12 2010
@@ -310,7 +310,13 @@ maybe_unlock(svn_ra_session_t *session,
 }
 
 /* Acquire a lock (of sorts) on the repository associated with the
- * given RA SESSION.
+ * given RA SESSION. This lock is just a revprop change attempt in a
+ * time-delay loop. This function is duplicated by svnrdump in
+ * load_editor.c.
+ *
+ * ### TODO: Make this function more generic and
+ * expose it through a header for use by other Subversion
+ * applications to avoid duplication.
  */
 static svn_error_t *
 get_lock(const svn_string_t **lock_string_p,

Modified: subversion/branches/atomic-revprop/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/tests/cmdline/authz_tests.py?rev=999427&r1=999426&r2=999427&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/atomic-revprop/subversion/tests/cmdline/authz_tests.py Tue Sep 21 14:14:12 2010
@@ -1091,9 +1091,8 @@ test_list = [ None,
               Skip(wc_wc_copy, svntest.main.is_ra_type_file),
               Skip(wc_wc_copy_revert,
                    svntest.main.is_ra_type_file),
-              XFail(Skip(authz_recursive_ls,
-                         svntest.main.is_ra_type_file),
-                    svntest.main.is_ra_type_svn),
+              Skip(authz_recursive_ls,
+                   svntest.main.is_ra_type_file),
              ]
 
 if __name__ == '__main__':