You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/12/21 01:23:41 UTC

svn commit: r1424772 [3/4] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/win32/ subversion/bindings/cxxhl/include/ subversion/bindings/cxxhl/include/svncxxhl/ subversion/bindings/cxxhl/include/types/ subversion/bindings/cxxhl/s...

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c Fri Dec 21 00:23:39 2012
@@ -1422,29 +1422,21 @@ does_node_exist(svn_boolean_t *exists,
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
-/* Baton for passing args to init_db(). */
-struct init_db_baton
-{
-  /* output values */
-  apr_int64_t wc_id;
-  apr_int64_t repos_id;
-  /* input values */
-  const char *repos_root_url;
-  const char *repos_uuid;
-  const char *root_node_repos_relpath;
-  svn_revnum_t root_node_revision;
-  svn_depth_t root_node_depth;
-};
-
 /* Helper for create_db(). Initializes our wc.db schema.
- *
- * Implements svn_sqlite__transaction_callback_t. */
+ */
 static svn_error_t *
-init_db(void *baton,
+init_db(/* output values */
+        apr_int64_t *repos_id,
+        apr_int64_t *wc_id,
+        /* input values */
         svn_sqlite__db_t *db,
+        const char *repos_root_url,
+        const char *repos_uuid,
+        const char *root_node_repos_relpath,
+        svn_revnum_t root_node_revision,
+        svn_depth_t root_node_depth,
         apr_pool_t *scratch_pool)
 {
-  struct init_db_baton *idb = baton;
   svn_sqlite__stmt_t *stmt;
 
   /* Create the database's schema.  */
@@ -1454,33 +1446,33 @@ init_db(void *baton,
   SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_EXTERNALS));
 
   /* Insert the repository. */
-  SVN_ERR(create_repos_id(&idb->repos_id, idb->repos_root_url, idb->repos_uuid,
+  SVN_ERR(create_repos_id(repos_id, repos_root_url, repos_uuid,
                           db, scratch_pool));
 
   /* Insert the wcroot. */
   /* ### Right now, this just assumes wc metadata is being stored locally. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_WCROOT));
-  SVN_ERR(svn_sqlite__insert(&idb->wc_id, stmt));
+  SVN_ERR(svn_sqlite__insert(wc_id, stmt));
 
-  if (idb->root_node_repos_relpath)
+  if (root_node_repos_relpath)
     {
       svn_wc__db_status_t status = svn_wc__db_status_normal;
 
-      if (idb->root_node_revision > 0)
+      if (root_node_revision > 0)
         status = svn_wc__db_status_incomplete; /* Will be filled by update */
 
       SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_NODE));
       SVN_ERR(svn_sqlite__bindf(stmt, "isdsisrtst",
-                                idb->wc_id,          /* 1 */
+                                *wc_id,              /* 1 */
                                 "",                  /* 2 */
                                 0,                   /* op_depth is 0 for base */
                                 NULL,                /* 4 */
-                                idb->repos_id,
-                                idb->root_node_repos_relpath,
-                                idb->root_node_revision,
+                                *repos_id,
+                                root_node_repos_relpath,
+                                root_node_revision,
                                 presence_map, status, /* 8 */
                                 svn_token__to_word(depth_map,
-                                                   idb->root_node_depth),
+                                                   root_node_depth),
                                 kind_map, svn_kind_dir /* 10 */));
 
       SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -1513,23 +1505,16 @@ create_db(svn_sqlite__db_t **sdb,
           apr_pool_t *result_pool,
           apr_pool_t *scratch_pool)
 {
-  struct init_db_baton idb;
-
   SVN_ERR(svn_wc__db_util_open_db(sdb, dir_abspath, sdb_fname,
                                   svn_sqlite__mode_rwcreate, exclusive,
                                   NULL /* my_statements */,
                                   result_pool, scratch_pool));
 
-  idb.repos_root_url = repos_root_url;
-  idb.repos_uuid = repos_uuid;
-  idb.root_node_repos_relpath = root_node_repos_relpath;
-  idb.root_node_revision = root_node_revision;
-  idb.root_node_depth = root_node_depth;
-
-  SVN_ERR(svn_sqlite__with_lock(*sdb, init_db, &idb, scratch_pool));
-
-  *repos_id = idb.repos_id;
-  *wc_id = idb.wc_id;
+  SVN_SQLITE__WITH_LOCK(init_db(repos_id, wc_id,
+                                *sdb, repos_root_url, repos_uuid,
+                                root_node_repos_relpath, root_node_revision,
+                                root_node_depth, scratch_pool),
+                        *sdb);
 
   return SVN_NO_ERROR;
 }
@@ -4925,6 +4910,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t 
 svn_error_t *
 svn_wc__db_op_add_directory(svn_wc__db_t *db,
                             const char *local_abspath,
+                            const apr_hash_t *props,
                             const svn_skel_t *work_items,
                             apr_pool_t *scratch_pool)
 {
@@ -4948,6 +4934,11 @@ svn_wc__db_op_add_directory(svn_wc__db_t
   iwb.presence = svn_wc__db_status_normal;
   iwb.kind = svn_kind_dir;
   iwb.op_depth = relpath_depth(local_relpath);
+  if (props && apr_hash_count((apr_hash_t *)props))
+    {
+      iwb.update_actual_props = TRUE;
+      iwb.new_actual_props = props;
+    }
 
   iwb.work_items = work_items;
 
@@ -4965,6 +4956,7 @@ svn_wc__db_op_add_directory(svn_wc__db_t
 svn_error_t *
 svn_wc__db_op_add_file(svn_wc__db_t *db,
                        const char *local_abspath,
+                       const apr_hash_t *props,
                        const svn_skel_t *work_items,
                        apr_pool_t *scratch_pool)
 {
@@ -4988,6 +4980,11 @@ svn_wc__db_op_add_file(svn_wc__db_t *db,
   iwb.presence = svn_wc__db_status_normal;
   iwb.kind = svn_kind_file;
   iwb.op_depth = relpath_depth(local_relpath);
+  if (props && apr_hash_count((apr_hash_t *)props))
+    {
+      iwb.update_actual_props = TRUE;
+      iwb.new_actual_props = props;
+    }
 
   iwb.work_items = work_items;
 
@@ -5003,6 +5000,7 @@ svn_error_t *
 svn_wc__db_op_add_symlink(svn_wc__db_t *db,
                           const char *local_abspath,
                           const char *target,
+                          const apr_hash_t *props,
                           const svn_skel_t *work_items,
                           apr_pool_t *scratch_pool)
 {
@@ -5029,6 +5027,11 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
   iwb.presence = svn_wc__db_status_normal;
   iwb.kind = svn_kind_symlink;
   iwb.op_depth = relpath_depth(local_relpath);
+  if (props && apr_hash_count((apr_hash_t *)props))
+    {
+      iwb.update_actual_props = TRUE;
+      iwb.new_actual_props = props;
+    }
 
   iwb.target = target;
 
@@ -9166,6 +9169,7 @@ struct read_inherited_props_baton_t
 {
   apr_array_header_t *iprops;
   const char *propname;
+  const char *repos_root_url;
   apr_pool_t *result_pool;
 };
 
@@ -9288,7 +9292,15 @@ db_read_inherited_props(void *baton,
 
           /* If we didn't filter everything then keep this iprop. */
           if (apr_hash_count(cached_iprop->prop_hash))
-            svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+            {
+              /* Convert the repository relative path in the
+                 cache to a full URL. */
+              cached_iprop->path_or_url =
+                svn_path_url_add_component2(ripb->repos_root_url,
+                                            cached_iprop->path_or_url,
+                                            result_pool);
+              svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+            }
         }
     }
 
@@ -9307,9 +9319,14 @@ svn_wc__db_read_inherited_props(apr_arra
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
   struct read_inherited_props_baton_t ripb;
+  const char *repos_root_url;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
+  SVN_ERR(svn_wc__internal_get_repos_info(&repos_root_url, NULL, db,
+                                          local_abspath, scratch_pool,
+                                          scratch_pool));
+
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
                                                 db, local_abspath,
                                                 scratch_pool, scratch_pool));
@@ -9317,6 +9334,7 @@ svn_wc__db_read_inherited_props(apr_arra
 
   ripb.iprops = NULL;
   ripb.propname = propname;
+  ripb.repos_root_url = repos_root_url;
   ripb.result_pool = result_pool;
 
   SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_read_inherited_props,
@@ -9501,9 +9519,9 @@ svn_wc__db_read_children_of_working_node
 /* Baton for passing args to check_replace_txn(). */
 struct check_replace_baton
 {
-  svn_boolean_t *is_replace_root;
-  svn_boolean_t *base_replace;
-  svn_boolean_t is_replace;
+  svn_boolean_t *is_replace_root_p;
+  svn_boolean_t *base_replace_p;
+  svn_boolean_t *is_replace_p;
 };
 
 /* Helper for svn_wc__db_node_check_replace().
@@ -9518,6 +9536,7 @@ check_replace_txn(void *baton,
   struct check_replace_baton *crb = baton;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+  svn_boolean_t is_replace = FALSE;
   int replaced_op_depth;
   svn_wc__db_status_t replaced_status;
 
@@ -9560,11 +9579,15 @@ check_replace_txn(void *baton,
       && replaced_status != svn_wc__db_status_excluded
       && replaced_status != svn_wc__db_status_server_excluded
       && replaced_status != svn_wc__db_status_base_deleted)
-    crb->is_replace = TRUE;
+    {
+      is_replace = TRUE;
+      if (crb->is_replace_p)
+        *crb->is_replace_p = TRUE;
+    }
 
   replaced_op_depth = svn_sqlite__column_int(stmt, 0);
 
-  if (crb->base_replace)
+  if (crb->base_replace_p)
     {
       int op_depth = svn_sqlite__column_int(stmt, 0);
 
@@ -9582,13 +9605,13 @@ check_replace_txn(void *baton,
 
           base_status = svn_sqlite__column_token(stmt, 3, presence_map);
 
-          *crb->base_replace = (base_status != svn_wc__db_status_not_present);
+          *crb->base_replace_p = (base_status != svn_wc__db_status_not_present);
         }
     }
 
   SVN_ERR(svn_sqlite__reset(stmt));
 
-  if (!crb->is_replace_root || !crb->is_replace)
+  if (!crb->is_replace_root_p || !is_replace)
     return SVN_NO_ERROR;
 
   if (replaced_status != svn_wc__db_status_base_deleted)
@@ -9609,7 +9632,7 @@ check_replace_txn(void *baton,
         {
           /* Did we replace inside our directory? */
 
-          *crb->is_replace_root = (parent_op_depth == replaced_op_depth);
+          *crb->is_replace_root_p = (parent_op_depth == replaced_op_depth);
           SVN_ERR(svn_sqlite__reset(stmt));
           return SVN_NO_ERROR;
         }
@@ -9622,9 +9645,9 @@ check_replace_txn(void *baton,
       SVN_ERR(svn_sqlite__reset(stmt));
 
       if (!have_row)
-        *crb->is_replace_root = TRUE; /* Parent is no replacement */
+        *crb->is_replace_root_p = TRUE; /* Parent is no replacement */
       else if (parent_op_depth < replaced_op_depth)
-        *crb->is_replace_root = TRUE; /* Parent replaces a lower layer */
+        *crb->is_replace_root_p = TRUE; /* Parent replaces a lower layer */
       /*else // No replacement root */
   }
 
@@ -9652,24 +9675,21 @@ svn_wc__db_node_check_replace(svn_boolea
 
   if (is_replace_root)
     *is_replace_root = FALSE;
-  if (is_replace)
-    *is_replace = FALSE;
   if (base_replace)
     *base_replace = FALSE;
+  if (is_replace)
+    *is_replace = FALSE;
 
   if (local_relpath[0] == '\0')
     return SVN_NO_ERROR; /* Working copy root can't be replaced */
 
-  crb.is_replace_root = is_replace_root;
-  crb.base_replace = base_replace;
-  crb.is_replace = FALSE;
+  crb.is_replace_root_p = is_replace_root;
+  crb.base_replace_p = base_replace;
+  crb.is_replace_p = is_replace;
 
   SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, check_replace_txn, &crb,
                               scratch_pool));
 
-  if (is_replace)
-    *is_replace = crb.is_replace;
-
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h Fri Dec 21 00:23:39 2012
@@ -1378,31 +1378,37 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t 
 
 /* ### add a new versioned directory. a list of children is NOT passed
    ### since they are added in future, distinct calls to db_op_add_*.
-   ### this is freshly added, so it has no properties.  */
+   PROPS gives the properties; empty or NULL means none. */
 /* ### do we need a CONFLICTS param?  */
 svn_error_t *
 svn_wc__db_op_add_directory(svn_wc__db_t *db,
                             const char *local_abspath,
+                            const apr_hash_t *props,
                             const svn_skel_t *work_items,
                             apr_pool_t *scratch_pool);
 
 
-/* ### as a new file, there are no properties. this file has no "pristine"
+/* Add a file.
+   PROPS gives the properties; empty or NULL means none.
+   ### this file has no "pristine"
    ### contents, so a checksum [reference] is not required.  */
 /* ### do we need a CONFLICTS param?  */
 svn_error_t *
 svn_wc__db_op_add_file(svn_wc__db_t *db,
                        const char *local_abspath,
+                       const apr_hash_t *props,
                        const svn_skel_t *work_items,
                        apr_pool_t *scratch_pool);
 
 
-/* ### newly added symlinks have no properties.  */
+/* Add a symlink.
+   PROPS gives the properties; empty or NULL means none. */
 /* ### do we need a CONFLICTS param?  */
 svn_error_t *
 svn_wc__db_op_add_symlink(svn_wc__db_t *db,
                           const char *local_abspath,
                           const char *target,
+                          const apr_hash_t *props,
                           const svn_skel_t *work_items,
                           apr_pool_t *scratch_pool);
 

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c Fri Dec 21 00:23:39 2012
@@ -288,20 +288,6 @@ svn_wc__db_pristine_get_tempdir(const ch
 }
 
 
-/* Data for pristine_install_txn(). */
-typedef struct pristine_install_baton_t
-{
-  /* The path to the source file that is to be moved into place. */
-  const char *tempfile_abspath;
-  /* The target path for the file (within the pristine store). */
-  const char *pristine_abspath;
-  /* The pristine text's SHA-1 checksum. */
-  const svn_checksum_t *sha1_checksum;
-  /* The pristine text's MD-5 checksum. */
-  const svn_checksum_t *md5_checksum;
-} pristine_install_baton_t;
-
-
 /* Install the pristine text described by BATON into the pristine store of
  * SDB.  If it is already stored then just delete the new file
  * BATON->tempfile_abspath.
@@ -312,11 +298,17 @@ typedef struct pristine_install_baton_t
  * Implements 'notes/wc-ng/pristine-store' section A-3(a).
  * Implements svn_sqlite__transaction_callback_t. */
 static svn_error_t *
-pristine_install_txn(void *baton,
-                     svn_sqlite__db_t *sdb,
+pristine_install_txn(svn_sqlite__db_t *sdb,
+                     /* The path to the source file that is to be moved into place. */
+                     const char *tempfile_abspath,
+                     /* The target path for the file (within the pristine store). */
+                     const char *pristine_abspath,
+                     /* The pristine text's SHA-1 checksum. */
+                     const svn_checksum_t *sha1_checksum,
+                     /* The pristine text's MD-5 checksum. */
+                     const svn_checksum_t *md5_checksum,
                      apr_pool_t *scratch_pool)
 {
-  pristine_install_baton_t *b = baton;
   apr_finfo_t finfo;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
@@ -325,7 +317,7 @@ pristine_install_txn(void *baton,
   /* If this pristine text is already present in the store, just keep it:
    * delete the new one and return. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   SVN_ERR(svn_sqlite__reset(stmt));
   if (have_row)
@@ -335,30 +327,30 @@ pristine_install_txn(void *baton,
        * ### We could check much more. */
       {
         apr_finfo_t finfo1, finfo2;
-        SVN_ERR(svn_io_stat(&finfo1, b->tempfile_abspath, APR_FINFO_SIZE,
+        SVN_ERR(svn_io_stat(&finfo1, tempfile_abspath, APR_FINFO_SIZE,
                             scratch_pool));
-        SVN_ERR(svn_io_stat(&finfo2, b->pristine_abspath, APR_FINFO_SIZE,
+        SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
                             scratch_pool));
         if (finfo1.size != finfo2.size)
           {
             return svn_error_createf(
               SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
               _("New pristine text '%s' has different size: %ld versus %ld"),
-              svn_checksum_to_cstring_display(b->sha1_checksum, scratch_pool),
+              svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
               (long int)finfo1.size, (long int)finfo2.size);
           }
       }
 #endif
 
       /* Remove the temp file: it's already there */
-      SVN_ERR(svn_io_remove_file2(b->tempfile_abspath,
+      SVN_ERR(svn_io_remove_file2(tempfile_abspath,
                                   FALSE /* ignore_enoent */, scratch_pool));
       return SVN_NO_ERROR;
     }
 
   /* Move the file to its target location.  (If it is already there, it is
    * an orphan file and it doesn't matter if we overwrite it.) */
-  err = svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+  err = svn_io_file_rename(tempfile_abspath, pristine_abspath,
                            scratch_pool);
 
   /* Maybe the directory doesn't exist yet? */
@@ -366,7 +358,7 @@ pristine_install_txn(void *baton,
     {
       svn_error_t *err2;
 
-      err2 = svn_io_dir_make(svn_dirent_dirname(b->pristine_abspath,
+      err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
                                                 scratch_pool),
                              APR_OS_DEFAULT, scratch_pool);
 
@@ -377,19 +369,19 @@ pristine_install_txn(void *baton,
         /* We could create a directory: retry install */
         svn_error_clear(err);
 
-      SVN_ERR(svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+      SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
                            scratch_pool));
     }
   else
     SVN_ERR(err);
 
-  SVN_ERR(svn_io_stat(&finfo, b->pristine_abspath, APR_FINFO_SIZE,
+  SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
                       scratch_pool));
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_INSERT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, b->md5_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
   SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
@@ -407,7 +399,7 @@ svn_wc__db_pristine_install(svn_wc__db_t
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
   const char *wri_abspath;
-  struct pristine_install_baton_t b;
+  const char *pristine_abspath;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
   SVN_ERR_ASSERT(sha1_checksum != NULL);
@@ -429,19 +421,18 @@ svn_wc__db_pristine_install(svn_wc__db_t
                               wri_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  b.tempfile_abspath = tempfile_abspath;
-  b.sha1_checksum = sha1_checksum;
-  b.md5_checksum = md5_checksum;
-
-  SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+  SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
                              sha1_checksum,
                              scratch_pool, scratch_pool));
 
   /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
    * at the disk, to ensure no concurrent pristine install/delete txn. */
-  SVN_ERR(svn_sqlite__with_immediate_transaction(wcroot->sdb,
-                                                 pristine_install_txn, &b,
-                                                 scratch_pool));
+  SVN_SQLITE__WITH_IMMEDIATE_TXN(
+    pristine_install_txn(wcroot->sdb,
+                         tempfile_abspath, pristine_abspath,
+                         sha1_checksum, md5_checksum,
+                         scratch_pool),
+    wcroot->sdb);
 
   return SVN_NO_ERROR;
 }
@@ -531,8 +522,15 @@ struct pristine_transfer_baton
   svn_cancel_func_t cancel_func;
   void * cancel_baton;
 
-  /* pristine install baton, filled from pristine_transfer() */
-  struct pristine_install_baton_t ib;
+  /* The following fields are filled in by pristine_transfer(). */
+  /* The path to the source file that is to be moved into place. */
+  const char *tempfile_abspath;
+  /* The target path for the file (within the pristine store). */
+  const char *pristine_abspath;
+  /* The pristine text's SHA-1 checksum. */
+  const svn_checksum_t *sha1_checksum;
+  /* The pristine text's MD-5 checksum. */
+  const svn_checksum_t *md5_checksum;
 };
 
 /* Transaction implementation of svn_wc__db_pristine_transfer().
@@ -555,8 +553,12 @@ pristine_transfer(void *baton, svn_wc__d
                                   pristine_transfer, tb, scratch_pool));
 
       /* And do the final install, while we still have the dst lock */
-      if (tb->ib.tempfile_abspath)
-        SVN_ERR(pristine_install_txn(&(tb->ib), tb->dst_wcroot->sdb,
+      if (tb->tempfile_abspath)
+        SVN_ERR(pristine_install_txn(tb->dst_wcroot->sdb,
+                                     tb->tempfile_abspath,
+                                     tb->pristine_abspath,
+                                     tb->sha1_checksum,
+                                     tb->md5_checksum,
                                      scratch_pool));
       return SVN_NO_ERROR;
     }
@@ -564,7 +566,7 @@ pristine_transfer(void *baton, svn_wc__d
   /* We have a lock on tb->dst_wcroot and tb->src_wcroot */
 
   /* Get the right checksum if it wasn't passed */
-  if (!tb->ib.sha1_checksum)
+  if (!tb->sha1_checksum)
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
                                         STMT_SELECT_NODE_INFO));
@@ -575,19 +577,19 @@ pristine_transfer(void *baton, svn_wc__d
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
       if (have_row)
-        SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.sha1_checksum), stmt, 6,
+        SVN_ERR(svn_sqlite__column_checksum(&(tb->sha1_checksum), stmt, 6,
                                             scratch_pool));
 
       SVN_ERR(svn_sqlite__reset(stmt));
 
-      if (!tb->ib.sha1_checksum)
+      if (!tb->sha1_checksum)
         return SVN_NO_ERROR; /* Nothing to transfer */
     }
 
   /* Check if we have the pristine in the destination wcroot */
   SVN_ERR(svn_sqlite__get_statement(&stmt, tb->dst_wcroot->sdb,
                                     STMT_SELECT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->ib.sha1_checksum,
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->sha1_checksum,
                                     scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   SVN_ERR(svn_sqlite__reset(stmt));
@@ -599,7 +601,7 @@ pristine_transfer(void *baton, svn_wc__d
   /* Verify if the pristine actually exists and get the MD5 in one query */
   SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
                                     STMT_SELECT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->ib.sha1_checksum,
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->sha1_checksum,
                                     scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
@@ -609,9 +611,9 @@ pristine_transfer(void *baton, svn_wc__d
                                _("The pristine text with checksum '%s' was "
                                  "not found"),
                                svn_checksum_to_cstring_display(
-                                        tb->ib.sha1_checksum, scratch_pool));
+                                        tb->sha1_checksum, scratch_pool));
     }
-  SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.md5_checksum), stmt, 0,
+  SVN_ERR(svn_sqlite__column_checksum(&(tb->md5_checksum), stmt, 0,
                                       scratch_pool));
   SVN_ERR(svn_sqlite__reset(stmt));
 
@@ -631,7 +633,7 @@ pristine_transfer(void *baton, svn_wc__d
                                    scratch_pool, scratch_pool));
 
     SVN_ERR(get_pristine_fname(&src_abspath, tb->src_wcroot->abspath,
-                               tb->ib.sha1_checksum,
+                               tb->sha1_checksum,
                                scratch_pool, scratch_pool));
 
     SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
@@ -645,11 +647,11 @@ pristine_transfer(void *baton, svn_wc__d
     /* And now set the right information to install once we leave the
        src transaction */
 
-    SVN_ERR(get_pristine_fname(&(tb->ib.pristine_abspath),
+    SVN_ERR(get_pristine_fname(&(tb->pristine_abspath),
                                tb->dst_wcroot->abspath,
-                               tb->ib.sha1_checksum,
+                               tb->sha1_checksum,
                                scratch_pool, scratch_pool));
-    tb->ib.tempfile_abspath = tmp_abspath;
+    tb->tempfile_abspath = tmp_abspath;
   }
   return SVN_NO_ERROR;
 }
@@ -730,17 +732,8 @@ remove_file(const char *file_abspath,
   return SVN_NO_ERROR;
 }
 
-/* Data for pristine_remove_if_unreferenced_txn(). */
-typedef struct pristine_remove_baton_t
-{
-  svn_wc__db_wcroot_t *wcroot;
-  /* The pristine text's SHA-1 checksum. */
-  const svn_checksum_t *sha1_checksum;
-  /* The path to the pristine file (within the pristine store). */
-  const char *pristine_abspath;
-} pristine_remove_baton_t;
-
-/* If the pristine text referenced by BATON in SDB has a reference count of
+/* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
+ * within the pristine store is PRISTINE_ABSPATH, has a reference count of
  * zero, delete it (both the database row and the disk file).
  *
  * This function expects to be executed inside a SQLite txn that has already
@@ -748,18 +741,19 @@ typedef struct pristine_remove_baton_t
  *
  * Implements svn_sqlite__transaction_callback_t. */
 static svn_error_t *
-pristine_remove_if_unreferenced_txn(void *baton,
-                                    svn_sqlite__db_t *sdb,
+pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
+                                    svn_wc__db_wcroot_t *wcroot,
+                                    const svn_checksum_t *sha1_checksum,
+                                    const char *pristine_abspath,
                                     apr_pool_t *scratch_pool)
 {
-  pristine_remove_baton_t *b = baton;
   svn_sqlite__stmt_t *stmt;
   int affected_rows;
 
   /* Remove the DB row, if refcount is 0. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_DELETE_PRISTINE_IF_UNREFERENCED));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
   SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
 
   /* If we removed the DB row, then remove the file. */
@@ -774,7 +768,7 @@ pristine_remove_if_unreferenced_txn(void
       svn_boolean_t ignore_enoent = TRUE;
 #endif
 
-      SVN_ERR(remove_file(b->pristine_abspath, b->wcroot, ignore_enoent,
+      SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent,
                           scratch_pool));
     }
 
@@ -791,17 +785,17 @@ pristine_remove_if_unreferenced(svn_wc__
                                 const svn_checksum_t *sha1_checksum,
                                 apr_pool_t *scratch_pool)
 {
-  pristine_remove_baton_t b;
+  const char *pristine_abspath;
 
-  b.wcroot = wcroot;
-  b.sha1_checksum = sha1_checksum;
-  SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+  SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
                              sha1_checksum, scratch_pool, scratch_pool));
 
   /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
    * at the disk, to ensure no concurrent pristine install/delete txn. */
-  SVN_ERR(svn_sqlite__with_immediate_transaction(
-    wcroot->sdb, pristine_remove_if_unreferenced_txn, &b, scratch_pool));
+  SVN_SQLITE__WITH_IMMEDIATE_TXN(
+    pristine_remove_if_unreferenced_txn(
+      wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
+    wcroot->sdb);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c Fri Dec 21 00:23:39 2012
@@ -220,39 +220,81 @@ update_working_props(svn_wc_notify_state
 }
 
 
-/* Check whether the node at LOCAL_RELPATH in the working copy at WCROOT
- * is shadowed by some node at a higher op depth than EXPECTED_OP_DEPTH. */
+/* If LOCAL_ABSPATH is shadowed then raise a tree-conflict on the root
+   of the obstruction if such a tree-conflict does not already exist. */
 static svn_error_t *
-check_shadowed_node(svn_boolean_t *is_shadowed,
-                    int expected_op_depth,
+check_tree_conflict(svn_boolean_t *is_conflicted,
+                    struct tc_editor_baton *b,
                     const char *local_relpath,
-                    svn_wc__db_wcroot_t *wcroot)
+                    svn_node_kind_t kind,
+                    apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+  int dst_op_depth = relpath_depth(b->move_root_dst_relpath);
+  int op_depth;
+  const char *conflict_root_relpath = local_relpath;
+  const char *moved_to_relpath;
+  svn_skel_t *conflict;
+  svn_wc_conflict_version_t *version;
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_SELECT_LOWEST_WORKING_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, local_relpath,
+                            dst_op_depth));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    op_depth = svn_sqlite__column_int(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
 
-  while (have_row)
+  if (!have_row)
     {
-      int op_depth = svn_sqlite__column_int(stmt, 0);
-
-      if (op_depth > expected_op_depth)
-        {
-          *is_shadowed = TRUE;
-          SVN_ERR(svn_sqlite__reset(stmt));
+      *is_conflicted = FALSE;
+      return SVN_NO_ERROR;
+    }
 
-          return SVN_NO_ERROR;
-        }
+  *is_conflicted = TRUE;
 
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
+  while (relpath_depth(conflict_root_relpath) > op_depth)
+    conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath,
+                                                scratch_pool);
+
+  SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, b->wcroot,
+                                            conflict_root_relpath,
+                                            scratch_pool, scratch_pool));
+
+  if (conflict)
+    /* ### TODO: check this is the right sort of tree-conflict? */
+    return SVN_NO_ERROR;
+
+  SVN_ERR(svn_wc__db_scan_deletion_internal(NULL, &moved_to_relpath,
+                                            NULL, NULL,
+                                            b->wcroot, conflict_root_relpath,
+                                            scratch_pool, scratch_pool));
+
+  conflict = svn_wc__conflict_skel_create(scratch_pool);
+  SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                     conflict, NULL,
+                     svn_dirent_join(b->wcroot->abspath, conflict_root_relpath,
+                                     scratch_pool),
+                     (moved_to_relpath
+                      ? svn_wc_conflict_reason_moved_away
+                      : svn_wc_conflict_reason_deleted),
+                     svn_wc_conflict_action_edit,
+                     scratch_pool,
+                     scratch_pool));
+
+  version = svn_wc_conflict_version_create2(b->old_version->repos_url,
+                                            b->old_version->repos_uuid,
+                                            local_relpath,
+                                            b->old_version->peg_rev,
+                                            kind,
+                                            scratch_pool);
 
-  *is_shadowed = FALSE;
-  SVN_ERR(svn_sqlite__reset(stmt));
+  SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict, version,
+                                              scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, conflict_root_relpath,
+                                            conflict, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -272,9 +314,15 @@ tc_editor_alter_directory(void *baton,
   svn_kind_t move_dst_kind;
   working_node_version_t old_version, new_version;
   svn_wc__db_status_t status;
+  svn_boolean_t is_conflicted;
 
   SVN_ERR_ASSERT(expected_move_dst_revision == b->old_version->peg_rev);
 
+  SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, svn_node_dir,
+                              scratch_pool));
+  if (is_conflicted)
+    return SVN_NO_ERROR;
+
   /* Get kind, revision, and checksum of the moved-here node. */
   SVN_ERR(svn_wc__db_depth_get_info(&status, &move_dst_kind, &move_dst_revision,
                                     &move_dst_repos_relpath, NULL, NULL, NULL,
@@ -294,59 +342,45 @@ tc_editor_alter_directory(void *baton,
 
   if (new_props)
     {
-      svn_boolean_t is_shadowed;
+      const char *dst_abspath = svn_dirent_join(b->wcroot->abspath,
+                                                dst_relpath,
+                                                scratch_pool);
+      svn_wc_notify_state_t prop_state;
+      svn_skel_t *conflict_skel = NULL;
+      apr_hash_t *actual_props;
+      apr_array_header_t *propchanges;
+
+      SVN_ERR(update_working_props(&prop_state, &conflict_skel,
+                                   &propchanges, &actual_props,
+                                   b->db, dst_abspath,
+                                   &old_version, &new_version,
+                                   b->result_pool, scratch_pool));
 
-      /* If the node is shadowed by a higher layer, we need to flag a 
-       * tree conflict and must not touch the working node. */
-      SVN_ERR(check_shadowed_node(&is_shadowed,
-                                  relpath_depth(b->move_root_dst_relpath),
-                                  dst_relpath, b->wcroot));
-      if (is_shadowed)
+      if (conflict_skel)
         {
-          /* ### TODO flag tree conflict */
+          SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
+                                          b->db, move_dst_repos_relpath,
+                                          conflict_skel,
+                                          &old_version, &new_version,
+                                          b->result_pool, scratch_pool));
+          SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
+                                                    conflict_skel,
+                                                    scratch_pool));
         }
-      else
-        {
-          const char *dst_abspath = svn_dirent_join(b->wcroot->abspath,
-                                                    dst_relpath,
-                                                    scratch_pool);
-          svn_wc_notify_state_t prop_state;
-          svn_skel_t *conflict_skel = NULL;
-          apr_hash_t *actual_props;
-          apr_array_header_t *propchanges;
-
-          SVN_ERR(update_working_props(&prop_state, &conflict_skel,
-                                       &propchanges, &actual_props,
-                                       b->db, dst_abspath,
-                                       &old_version, &new_version,
-                                       b->result_pool, scratch_pool));
 
-          if (conflict_skel)
-            {
-              SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
-                                              b->db, move_dst_repos_relpath,
-                                              conflict_skel,
-                                              &old_version, &new_version,
-                                              b->result_pool, scratch_pool));
-              SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
-                                                        conflict_skel,
-                                                        scratch_pool));
-            }
-
-          if (b->notify_func)
-            {
-              svn_wc_notify_t *notify;
+      if (b->notify_func)
+        {
+          svn_wc_notify_t *notify;
 
-              notify = svn_wc_create_notify(dst_abspath,
-                                            svn_wc_notify_update_update,
-                                            scratch_pool);
-              notify->kind = svn_node_dir;
-              notify->content_state = svn_wc_notify_state_inapplicable;
-              notify->prop_state = prop_state;
-              notify->old_revision = b->old_version->peg_rev;
-              notify->revision = b->new_version->peg_rev;
-              b->notify_func(b->notify_baton, notify, scratch_pool);
-            }
+          notify = svn_wc_create_notify(dst_abspath,
+                                        svn_wc_notify_update_update,
+                                        scratch_pool);
+          notify->kind = svn_node_dir;
+          notify->content_state = svn_wc_notify_state_inapplicable;
+          notify->prop_state = prop_state;
+          notify->old_revision = b->old_version->peg_rev;
+          notify->revision = b->new_version->peg_rev;
+          b->notify_func(b->notify_baton, notify, scratch_pool);
         }
     }
 
@@ -503,6 +537,12 @@ tc_editor_alter_file(void *baton,
   svn_revnum_t move_dst_revision;
   svn_kind_t move_dst_kind;
   working_node_version_t old_version, new_version;
+  svn_boolean_t is_conflicted;
+
+  SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, svn_node_file,
+                              scratch_pool));
+  if (is_conflicted)
+    return SVN_NO_ERROR;
 
   /* Get kind, revision, and checksum of the moved-here node. */
   SVN_ERR(svn_wc__db_depth_get_info(NULL, &move_dst_kind, &move_dst_revision,
@@ -528,30 +568,16 @@ tc_editor_alter_file(void *baton,
   if (!svn_checksum_match(new_checksum, old_version.checksum)
       /* ### || props have changed */)
     {
-      svn_boolean_t is_shadowed;
+      svn_skel_t *work_item;
 
-      /* If the node is shadowed by a higher layer, we need to flag a 
-       * tree conflict and must not touch the working file. */
-      SVN_ERR(check_shadowed_node(&is_shadowed,
-                                  relpath_depth(b->move_root_dst_relpath),
-                                  dst_relpath, b->wcroot));
-      if (is_shadowed)
-        {
-          /* ### TODO flag tree conflict */
-        }
-      else
-        {
-          svn_skel_t *work_item;
-
-          SVN_ERR(update_working_file(&work_item, dst_relpath,
-                                      move_dst_repos_relpath,
-                                      &old_version, &new_version,
-                                      b->wcroot, b->db,
-                                      b->notify_func, b->notify_baton,
-                                      b->result_pool, scratch_pool));
-          *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
-                                            b->result_pool);
-        }
+      SVN_ERR(update_working_file(&work_item, dst_relpath,
+                                  move_dst_repos_relpath,
+                                  &old_version, &new_version,
+                                  b->wcroot, b->db,
+                                  b->notify_func, b->notify_baton,
+                                  b->result_pool, scratch_pool));
+      *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
+                                        b->result_pool);
     }
 
   return SVN_NO_ERROR;
@@ -753,14 +779,55 @@ get_tc_info(svn_wc_operation_t *operatio
           const char *repos_relpath;
           svn_revnum_t revision;
           svn_node_kind_t node_kind;
+          svn_wc__db_status_t status;
+
+          /* The scan dance: read_info then scan_delete then base_get
+             or scan_addition.  Use the internal/relpath functions
+             here? */
+          SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision,
+                                       &repos_relpath, &repos_root_url,
+                                       &repos_uuid, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL,
+                                       db, src_abspath, result_pool,
+                                       scratch_pool));
+          if (status == svn_wc__db_status_deleted)
+            {
+              const char *base_del_abspath, *work_del_abspath;
+              SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL,
+                                               &work_del_abspath,
+                                               NULL, db, src_abspath,
+                                               scratch_pool, scratch_pool));
+              SVN_ERR_ASSERT(base_del_abspath || work_del_abspath);
+              if (base_del_abspath)
+                {
+                  SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
+                                                   &repos_relpath,
+                                                   &repos_root_url,
+                                                   &repos_uuid,
+                                                   NULL, NULL, NULL, NULL, NULL,
+                                                   NULL, NULL, NULL, NULL, NULL,
+                                                   db, src_abspath, result_pool,
+                                                   scratch_pool));
+                }
+              else if (work_del_abspath)
+                {
+                  work_del_abspath = svn_dirent_dirname(work_del_abspath,
+                                                        scratch_pool);
+                  SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
+                                                   &repos_root_url, &repos_uuid,
+                                                   NULL, NULL, NULL,
+                                                   &revision, NULL, NULL,
+                                                   db, work_del_abspath,
+                                                   scratch_pool, scratch_pool));
+                  repos_relpath = svn_relpath_join(repos_relpath,
+                                     svn_dirent_skip_ancestor(work_del_abspath,
+                                                              src_abspath),
+                                                   scratch_pool);
+                }
+            }
 
-          /* Construct new_version from BASE info. */
-          SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
-                                           &repos_relpath, &repos_root_url,
-                                           &repos_uuid, NULL, NULL, NULL, NULL,
-                                           NULL, NULL, NULL, NULL, NULL, NULL,
-                                           db, src_abspath, result_pool,
-                                           scratch_pool));
           node_kind = svn__node_kind_from_kind(kind);
           *new_version = svn_wc_conflict_version_create2(repos_root_url,
                                                          repos_uuid,

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c Fri Dec 21 00:23:39 2012
@@ -153,8 +153,8 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
 
 /* Some helpful transaction helpers.
 
-   Instead of directly using SQLite transactions, these wrappers take care of
-   simple cases by allowing consumers to worry about wrapping the wcroot and
+   Instead of directly using SQLite transactions, these wrappers
+   relieve the consumer from the need to wrap the wcroot and
    local_relpath, which are almost always used within the transaction.
 
    This also means if we later want to implement some wc_db-specific txn

Modified: subversion/branches/ev2-export/subversion/svn/copy-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/copy-cmd.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/copy-cmd.c (original)
+++ subversion/branches/ev2-export/subversion/svn/copy-cmd.c Fri Dec 21 00:23:39 2012
@@ -68,7 +68,42 @@ svn_cl__copy(apr_getopt_t *os,
       svn_opt_revision_t *peg_revision = apr_palloc(pool,
                                                     sizeof(*peg_revision));
 
-      SVN_ERR(svn_opt_parse_path(peg_revision, &src, target, pool));
+      err = svn_opt_parse_path(peg_revision, &src, target, pool);
+
+      if (err)
+        {
+          /* Issue #3606: 'svn cp .@HEAD target' gives
+             svn: '@HEAD' is just a peg revision. Maybe try '@HEAD@' instead? 
+
+             This is caused by a first round of canonicalization in
+             svn_cl__args_to_target_array_print_reserved(). Undo that in an
+             attempt to fix this issue without revving many apis.
+           */
+          if (*target == '@' && err->apr_err == SVN_ERR_BAD_FILENAME)
+            {
+              svn_error_t *err2;
+
+              err2 = svn_opt_parse_path(peg_revision, &src,
+                                        apr_pstrcat(pool, ".", target,
+                                                    (const char *)NULL), pool);
+
+              if (err2)
+                {
+                  /* Fix attempt failed; return original error */
+                  svn_error_clear(err2);
+                }
+              else
+                {
+                  /* Error resolved. Use path */
+                  svn_error_clear(err);
+                  err = NULL;
+                }
+            }
+
+          if (err)
+              return svn_error_trace(err);
+        }
+
       source->path = src;
       source->revision = &(opt_state->start_revision);
       source->peg_revision = peg_revision;

Modified: subversion/branches/ev2-export/subversion/svn/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/help-cmd.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/help-cmd.c (original)
+++ subversion/branches/ev2-export/subversion/svn/help-cmd.c Fri Dec 21 00:23:39 2012
@@ -28,6 +28,7 @@
 /*** Includes. ***/
 
 #include "svn_string.h"
+#include "svn_config.h"
 #include "svn_error.h"
 #include "svn_version.h"
 #include "cl.h"
@@ -43,7 +44,8 @@ svn_cl__help(apr_getopt_t *os,
              void *baton,
              apr_pool_t *pool)
 {
-  svn_cl__opt_state_t *opt_state;
+  svn_cl__opt_state_t *opt_state = NULL;
+  svn_stringbuf_t *version_footer = NULL;
 
   /* xgettext: the %s is for SVN_VER_NUMBER. */
   char help_header_template[] =
@@ -69,14 +71,72 @@ svn_cl__help(apr_getopt_t *os,
   const char *ra_desc_start
     = _("The following repository access (RA) modules are available:\n\n");
 
-  svn_stringbuf_t *version_footer;
-
   if (baton)
-    opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
-  else
-    opt_state = NULL;
+    {
+      svn_cl__cmd_baton_t *const cmd_baton = baton;
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
+      /* Windows never actually stores plaintext passwords, it
+         encrypts the contents using CryptoAPI. ...
+
+         ... If CryptoAPI is available ... but it should be on all
+         versions of Windows that are even remotely interesting two
+         days before the scheduled end of the world, when this comment
+         is being written. */
+#  ifndef WIN32
+      svn_boolean_t store_auth_creds =
+        SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
+      svn_boolean_t store_passwords =
+        SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
+      svn_boolean_t store_plaintext_passwords = FALSE;
+      svn_config_t *cfg;
+
+      if (cmd_baton->ctx->config)
+        {
+          cfg = apr_hash_get(cmd_baton->ctx->config,
+                             SVN_CONFIG_CATEGORY_CONFIG,
+                             APR_HASH_KEY_STRING);
+          if (cfg)
+            {
+              SVN_ERR(svn_config_get_bool(cfg, &store_auth_creds,
+                                          SVN_CONFIG_SECTION_AUTH,
+                                          SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
+                                          store_auth_creds));
+              SVN_ERR(svn_config_get_bool(cfg, &store_passwords,
+                                          SVN_CONFIG_SECTION_AUTH,
+                                          SVN_CONFIG_OPTION_STORE_PASSWORDS,
+                                          store_passwords));
+            }
+          cfg = apr_hash_get(cmd_baton->ctx->config,
+                             SVN_CONFIG_CATEGORY_SERVERS,
+                             APR_HASH_KEY_STRING);
+          if (cfg)
+            {
+              const char *value;
+              SVN_ERR(svn_config_get_yes_no_ask
+                      (cfg, &value,
+                       SVN_CONFIG_SECTION_GLOBAL,
+                       SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
+                       SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
+              if (0 == svn_cstring_casecmp(value, SVN_CONFIG_TRUE))
+                store_plaintext_passwords = TRUE;
+            }
+        }
+
+      if (store_plaintext_passwords && store_auth_creds && store_passwords)
+        {
+          version_footer = svn_stringbuf_create(
+              _("WARNING: Plaintext password storage is enabled!\n\n"),
+              pool);
+          svn_stringbuf_appendcstr(version_footer, ra_desc_start);
+        }
+#  endif /* !WIN32 */
+#endif /* !SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE */
+
+      opt_state = cmd_baton->opt_state;
+    }
 
-  version_footer = svn_stringbuf_create(ra_desc_start, pool);
+  if (!version_footer)
+    version_footer = svn_stringbuf_create(ra_desc_start, pool);
   SVN_ERR(svn_ra_print_modules(version_footer, pool));
 
   return svn_opt_print_help4(os,

Modified: subversion/branches/ev2-export/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/svn.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/svn.c (original)
+++ subversion/branches/ev2-export/subversion/svn/svn.c Fri Dec 21 00:23:39 2012
@@ -101,6 +101,7 @@ typedef enum svn_cl__longopt_t {
   opt_no_ignore,
   opt_no_unlock,
   opt_non_interactive,
+  opt_force_interactive,
   opt_old_cmd,
   opt_record_only,
   opt_relocate,
@@ -229,7 +230,13 @@ const apr_getopt_option_t svn_cl__option
                        "                             "
                        "with '--non-interactive')") },
   {"non-interactive", opt_non_interactive, 0,
-                    N_("do no interactive prompting")},
+                    N_("do no interactive prompting (default is to prompt\n"
+                       "                             "
+                       "only if standard input is a terminal device)")},
+  {"force-interactive", opt_force_interactive, 0,
+                    N_("do interactive prompting even if standard input\n"
+                       "                             "
+                       "is not a terminal device")},
   {"dry-run",       opt_dry_run, 0,
                     N_("try operation but make no changes")},
   {"ignore-ancestry", opt_ignore_ancestry, 0,
@@ -401,7 +408,8 @@ const apr_getopt_option_t svn_cl__option
    willy-nilly to every invocation of 'svn') . */
 const int svn_cl__global_options[] =
 { opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive,
-  opt_trust_server_cert, opt_config_dir, opt_config_options, 0
+  opt_force_interactive, opt_trust_server_cert, opt_config_dir,
+  opt_config_options, 0
 };
 
 /* Options for giving a log message.  (Some of these also have other uses.)
@@ -730,7 +738,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "          (the 'automatic' merge)\n"
 "       2. merge [-c M[,N...] | -r N:M ...] SOURCE[@REV] [TARGET_WCPATH]\n"
 "          (the 'cherry-pick' merge)\n"
-"       3. merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]\n"
+"       3. merge SOURCE1[@REV1] SOURCE2[@REV2] [TARGET_WCPATH]\n"
 "          (the '2-URL' merge)\n"
 "\n"
 "  1. This form, with one source path and no revision range, is called\n"
@@ -915,26 +923,27 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "\n"
 "  3. This form is called a '2-URL merge':\n"
 "\n"
-"       svn merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]\n"
-"\n"
-"     Two source URLs are specified, together with two revisions N and M.\n"
-"     The two sources are compared at the specified revisions, and the\n"
-"     difference is applied to TARGET_WCPATH, which is a path to a working\n"
-"     copy of another branch. The three branches involved can be completely\n"
-"     unrelated.\n"
+"       svn merge SOURCE1[@REV1] SOURCE2[@REV2] [TARGET_WCPATH]\n"
 "\n"
 "     You should use this merge variant only if the other variants do not\n"
 "     apply to your situation, as this variant can be quite complex to\n"
 "     master.\n"
 "\n"
+"     Two source URLs are specified, identifying two trees on the same\n"
+"     branch or on different branches. The trees are compared and the\n"
+"     difference from SOURCE1@REV1 to SOURCE2@REV2 is applied to the\n"
+"     working copy of the target branch at TARGET_WCPATH. The target\n"
+"     branch may be the same as one or both sources, or different again.\n"
+"     The three branches involved can be completely unrelated.\n"
+"\n"
 "     If TARGET_WCPATH is omitted, a default value of '.' is assumed.\n"
 "     However, in the special case where both sources refer to a file node\n"
-"     with the same basename and a similarly named file is also found within\n"
-"     '.', the differences will be applied to that local file.  The source\n"
-"     revisions default to HEAD if omitted.\n"
+"     with the same name and a file with the same name is also found within\n"
+"     '.', the differences will be applied to that local file. The source\n"
+"     revisions REV1 and REV2 default to HEAD if omitted.\n"
 "\n"
-"     The sources can also be specified as working copy paths, in which case\n"
-"     the URLs of the merge sources are derived from the working copies.\n"
+"     SOURCE1 and/or SOURCE2 can also be specified as a working copy path,\n"
+"     in which case the merge source URL is derived from the working copy.\n"
 "\n"
 "       - 2-URL Merge Example -\n"
 "\n"
@@ -1659,6 +1668,7 @@ sub_main(int argc, const char *argv[], a
   svn_config_t *cfg_config;
   svn_boolean_t descend = TRUE;
   svn_boolean_t interactive_conflicts = FALSE;
+  svn_boolean_t force_interactive = FALSE;
   svn_boolean_t use_notifier = TRUE;
   apr_hash_t *changelists;
   const char *sqlite_exclusive;
@@ -1982,6 +1992,9 @@ sub_main(int argc, const char *argv[], a
       case opt_non_interactive:
         opt_state.non_interactive = TRUE;
         break;
+      case opt_force_interactive:
+        force_interactive = TRUE;
+        break;
       case opt_trust_server_cert:
         opt_state.trust_server_cert = TRUE;
         break;
@@ -2191,6 +2204,20 @@ sub_main(int argc, const char *argv[], a
       }
     }
 
+  /* The --non-interactive and --force-interactive options are mutually
+   * exclusive. */
+  if (opt_state.non_interactive && force_interactive)
+    {
+      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("--non-interactive and --force-interactive "
+                               "are mutually exclusive"));
+      return EXIT_ERROR(err);
+    }
+  else
+    opt_state.non_interactive = !svn_cmdline__be_interactive(
+                                  opt_state.non_interactive,
+                                  force_interactive);
+
   /* Turn our hash of changelists into an array of unique ones. */
   SVN_INT_ERR(svn_hash_keys(&(opt_state.changelists), changelists, pool));
 

Modified: subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c Fri Dec 21 00:23:39 2012
@@ -101,6 +101,14 @@ struct dump_edit_baton {
   /* A backdoor ra session to fetch additional information during the edit. */
   svn_ra_session_t *ra_session;
 
+  /* The repository relpath of the anchor of the editor when driven
+     via the RA update mechanism; NULL otherwise. (When the editor is
+     driven via the RA "replay" mechanism instead, the editor is
+     always anchored at the repository, we don't need to prepend an
+     anchor path to the dumped node paths, and open_root() doesn't
+     need to manufacture directory additions.)  */
+  const char *update_anchor_relpath;
+
   /* Pool for per-revision allocations */
   apr_pool_t *pool;
 
@@ -308,14 +316,22 @@ dump_node(struct dump_edit_baton *eb,
           svn_revnum_t copyfrom_rev,
           apr_pool_t *pool)
 {
+  const char *node_relpath = repos_relpath;
+
   assert(svn_relpath_is_canonical(repos_relpath));
   assert(!copyfrom_path || svn_relpath_is_canonical(copyfrom_path));
 
-  /* Node-path: commons/STATUS */
+  /* Add the edit root relpath prefix if necessary. */
+  if (eb->update_anchor_relpath)
+    node_relpath = svn_relpath_join(eb->update_anchor_relpath,
+                                    node_relpath, pool);
+
+  /* Node-path: ... */
   SVN_ERR(svn_stream_printf(eb->stream, pool,
-                            SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n", repos_relpath));
+                            SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+                            node_relpath));
 
-  /* Node-kind: file */
+  /* Node-kind: "file" | "dir" */
   if (kind == svn_node_file)
     SVN_ERR(svn_stream_printf(eb->stream, pool,
                               SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
@@ -330,13 +346,24 @@ dump_node(struct dump_edit_baton *eb,
     case svn_node_action_change:
       /* We are here after a change_file_prop or change_dir_prop. They
          set up whatever dump_props they needed to- nothing to
-         do here but print node action information */
+         do here but print node action information.
+
+         Node-action: change.  */
       SVN_ERR(svn_stream_puts(eb->stream,
                               SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
       break;
 
     case svn_node_action_replace:
-      if (!is_copy)
+      if (is_copy)
+        {
+          /* Delete the original, and then re-add the replacement as a
+             copy using recursive calls into this function. */
+          SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_delete,
+                            FALSE, NULL, SVN_INVALID_REVNUM, pool));
+          SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_add,
+                            is_copy, copyfrom_path, copyfrom_rev, pool));
+        }
+      else
         {
           /* Node-action: replace */
           SVN_ERR(svn_stream_puts(eb->stream,
@@ -346,24 +373,11 @@ dump_node(struct dump_edit_baton *eb,
           /* Wait for a change_*_prop to be called before dumping
              anything */
           eb->dump_props = TRUE;
-          break;
         }
-      /* More complex case: is_copy is true, and copyfrom_path/
-         copyfrom_rev are present: delete the original, and then re-add
-         it */
-
-      SVN_ERR(svn_stream_puts(eb->stream,
-                              SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n\n"));
-
-      /* Recurse: Print an additional add-with-history record. */
-      SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_add,
-                        is_copy, copyfrom_path, copyfrom_rev, pool));
-
-      /* We can leave this routine quietly now, don't need to dump any
-         content; that was already done in the second record. */
       break;
 
     case svn_node_action_delete:
+      /* Node-action: delete */
       SVN_ERR(svn_stream_puts(eb->stream,
                               SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
 
@@ -371,44 +385,54 @@ dump_node(struct dump_edit_baton *eb,
          print a couple of newlines because we're not dumping props or
          text. */
       SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+
       break;
 
     case svn_node_action_add:
+      /* Node-action: add */
       SVN_ERR(svn_stream_puts(eb->stream,
                               SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
 
-      if (!is_copy)
+      if (is_copy)
         {
-          /* eb->dump_props for files is handled in close_file
-             which is called immediately.  However, directories are not
-             closed until all the work inside them has been done;
-             eb->dump_props for directories is handled in all the
-             functions that can possibly be called after add_directory:
-             add_directory, open_directory, delete_entry, close_directory,
-             add_file, open_file. change_dir_prop is a special case. */
-
-          /* Wait for a change_*_prop to be called before dumping
-             anything */
-          eb->dump_props = TRUE;
-          break;
+          /* Node-copyfrom-rev / Node-copyfrom-path */
+          SVN_ERR(svn_stream_printf(eb->stream, pool,
+                                    SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
+                                    ": %ld\n"
+                                    SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
+                                    ": %s\n",
+                                    copyfrom_rev, copyfrom_path));
+
+          /* Ugly hack: If a directory was copied from a previous
+             revision, nothing like close_file() will be called to write two
+             blank lines. If change_dir_prop() is called, props are dumped
+             (along with the necessary PROPS-END\n\n and we're good. So
+             set DUMP_NEWLINES here to print the newlines unless
+             change_dir_prop() is called next otherwise the `svnadmin load`
+             parser will fail.  */
+          if (kind == svn_node_dir)
+            eb->dump_newlines = TRUE;
         }
+      else
+        {
+          /* eb->dump_props (for files) is handled in close_file()
+             which is called immediately.
 
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
-                                SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
-                                ": %ld\n"
-                                SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
-                                ": %s\n",
-                                copyfrom_rev, copyfrom_path));
+             However, directories are not closed until all the work
+             inside them has been done; eb->dump_props (for directories)
+             is handled (via dump_pending()) in all the functions that
+             can possibly be called after add_directory():
+
+               - add_directory()
+               - open_directory()
+               - delete_entry()
+               - close_directory()
+               - add_file()
+               - open_file()
 
-      /* Ugly hack: If a directory was copied from a previous
-         revision, nothing like close_file() will be called to write two
-         blank lines. If change_dir_prop() is called, props are dumped
-         (along with the necessary PROPS-END\n\n and we're good. So
-         set DUMP_NEWLINES here to print the newlines unless
-         change_dir_prop() is called next otherwise the `svnadmin load`
-         parser will fail.  */
-      if (kind == svn_node_dir)
-        eb->dump_newlines = TRUE;
+             change_dir_prop() is a special case. */
+          eb->dump_props = TRUE;
+        }
 
       break;
     }
@@ -416,23 +440,42 @@ dump_node(struct dump_edit_baton *eb,
 }
 
 static svn_error_t *
-open_root(void *edit_baton,
-          svn_revnum_t base_revision,
-          apr_pool_t *pool,
-          void **root_baton)
+dump_mkdir(struct dump_edit_baton *eb,
+           const char *repos_relpath,
+           apr_pool_t *pool)
 {
-  struct dump_edit_baton *eb = edit_baton;
+  svn_stringbuf_t *prop_header, *prop_content;
+  apr_size_t len;
+  const char *buf;
 
-  /* Clear the per-revision pool after each revision */
-  svn_pool_clear(eb->pool);
+  /* Node-path: ... */
+  SVN_ERR(svn_stream_printf(eb->stream, pool,
+                            SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+                            repos_relpath));
 
-  eb->props = apr_hash_make(eb->pool);
-  eb->deleted_props = apr_hash_make(eb->pool);
-  eb->propstring = svn_stringbuf_create_empty(eb->pool);
+  /* Node-kind: dir */
+  SVN_ERR(svn_stream_printf(eb->stream, pool,
+                            SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
 
-  *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
-                               edit_baton, NULL, FALSE, eb->pool);
-  LDR_DBG(("open_root %p\n", *root_baton));
+  /* Node-action: add */
+  SVN_ERR(svn_stream_puts(eb->stream,
+                          SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+
+  /* Dump the (empty) property block. */
+  SVN_ERR(get_props_content(&prop_header, &prop_content,
+                            apr_hash_make(pool), apr_hash_make(pool),
+                            pool, pool));
+  len = prop_header->len;
+  SVN_ERR(svn_stream_write(eb->stream, prop_header->data, &len));
+  len = prop_content->len;
+  buf = apr_psprintf(pool, SVN_REPOS_DUMPFILE_CONTENT_LENGTH
+                     ": %" APR_SIZE_T_FMT "\n", len);
+  SVN_ERR(svn_stream_puts(eb->stream, buf));
+  SVN_ERR(svn_stream_puts(eb->stream, "\n"));
+  SVN_ERR(svn_stream_write(eb->stream, prop_content->data, &len));
+
+  /* Newlines to tie it all off. */
+  SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
 
   return SVN_NO_ERROR;
 }
@@ -456,6 +499,77 @@ dump_pending(struct dir_baton *pb,
 }
 
 static svn_error_t *
+open_root(void *edit_baton,
+          svn_revnum_t base_revision,
+          apr_pool_t *pool,
+          void **root_baton)
+{
+  struct dump_edit_baton *eb = edit_baton;
+  struct dir_baton *new_db = NULL;
+  
+  /* Clear the per-revision pool after each revision */
+  svn_pool_clear(eb->pool);
+
+  eb->props = apr_hash_make(eb->pool);
+  eb->deleted_props = apr_hash_make(eb->pool);
+  eb->propstring = svn_stringbuf_create_empty(eb->pool);
+
+  LDR_DBG(("open_root %p\n", *root_baton));
+
+  if (eb->update_anchor_relpath)
+    {
+      int i;
+      const char *parent_path = eb->update_anchor_relpath;
+      apr_array_header_t *dirs_to_add =
+        apr_array_make(pool, 4, sizeof(const char *));
+      apr_pool_t *iterpool = svn_pool_create(pool);
+
+      while (! svn_path_is_empty(parent_path))
+        {
+          APR_ARRAY_PUSH(dirs_to_add, const char *) = parent_path;
+          parent_path = svn_relpath_dirname(parent_path, pool);
+        }
+
+      for (i = dirs_to_add->nelts; i; --i)
+        {
+          const char *dir_to_add =
+            APR_ARRAY_IDX(dirs_to_add, i - 1, const char *);
+
+          svn_pool_clear(iterpool);
+
+          /* For parents of the source directory, we just manufacture
+             the adds ourselves. */
+          if (i > 1)
+            {
+              SVN_ERR(dump_mkdir(eb, dir_to_add, iterpool));
+            }
+          else
+            {
+              /* ... but for the source directory itself, we'll defer
+                 to letting the typical plumbing handle this task. */
+              new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
+                                      edit_baton, NULL, TRUE, pool);
+              SVN_ERR(dump_node(eb, new_db->repos_relpath, svn_node_dir,
+                                svn_node_action_add, FALSE, NULL, SVN_INVALID_REVNUM,
+                                pool));
+              new_db->written_out = TRUE;
+            }
+        }
+      svn_pool_destroy(iterpool);
+    }
+
+  if (! new_db)
+    {
+      new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
+                              edit_baton, NULL, FALSE, pool);
+    }
+
+  *root_baton = new_db;
+    
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 delete_entry(const char *path,
              svn_revnum_t revision,
              void *parent_baton,
@@ -1014,6 +1128,7 @@ svn_rdump__get_dump_editor(const svn_del
                            svn_revnum_t revision,
                            svn_stream_t *stream,
                            svn_ra_session_t *ra_session,
+                           const char *update_anchor_relpath,
                            svn_cancel_func_t cancel_func,
                            void *cancel_baton,
                            apr_pool_t *pool)
@@ -1026,6 +1141,7 @@ svn_rdump__get_dump_editor(const svn_del
   eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton));
   eb->stream = stream;
   eb->ra_session = ra_session;
+  eb->update_anchor_relpath = update_anchor_relpath;
   eb->current_revision = revision;
 
   /* Create a special per-revision pool */

Modified: subversion/branches/ev2-export/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnrdump/load_editor.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/ev2-export/subversion/svnrdump/load_editor.c Fri Dec 21 00:23:39 2012
@@ -855,6 +855,8 @@ set_revision_property(void *baton,
 {
   struct revision_baton *rb = baton;
 
+  SVN_ERR(svn_rdump__normalize_prop(name, &value, rb->pool));
+  
   SVN_ERR(svn_repos__validate_prop(name, value, rb->pool));
 
   if (rb->rev > 0)
@@ -934,6 +936,8 @@ set_node_property(void *baton,
         }
     }
 
+  SVN_ERR(svn_rdump__normalize_prop(name, &value, pool));
+
   SVN_ERR(svn_repos__validate_prop(name, value, pool));
 
   switch (nb->kind)

Modified: subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c Fri Dec 21 00:23:39 2012
@@ -23,6 +23,7 @@
  */
 
 #include <apr_signal.h>
+#include <apr_uri.h>
 
 #include "svn_pools.h"
 #include "svn_cmdline.h"
@@ -79,6 +80,7 @@ enum svn_svnrdump__longopt_t
     opt_auth_password,
     opt_auth_nocache,
     opt_non_interactive,
+    opt_force_interactive,
     opt_incremental,
     opt_trust_server_cert,
     opt_version
@@ -90,7 +92,8 @@ enum svn_svnrdump__longopt_t
                                    opt_auth_password, \
                                    opt_auth_nocache, \
                                    opt_trust_server_cert, \
-                                   opt_non_interactive
+                                   opt_non_interactive, \
+                                   opt_force_interactive
 
 static const svn_opt_subcommand_desc2_t svnrdump__cmd_table[] =
 {
@@ -126,7 +129,13 @@ static const apr_getopt_option_t svnrdum
     {"password",      opt_auth_password, 1,
                       N_("specify a password ARG")},
     {"non-interactive", opt_non_interactive, 0,
-                      N_("do no interactive prompting")},
+                      N_("do no interactive prompting (default is to prompt\n"
+                         "                             "
+                         "only if standard input is a terminal device)")},
+    {"force-interactive", opt_force_interactive, 0,
+                      N_("do interactive prompting even if standard input\n"
+                         "                             "
+                         "is not a terminal device")},
     {"no-auth-cache", opt_auth_nocache, 0,
                       N_("do not cache authentication tokens")},
     {"help",          'h', 0,
@@ -223,7 +232,7 @@ replay_revstart(svn_revnum_t revision,
 
   SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
                                      rb->stdout_stream, rb->extra_ra_session,
-                                     check_cancel, NULL, pool));
+                                     NULL, check_cancel, NULL, pool));
 
   return SVN_NO_ERROR;
 }
@@ -298,7 +307,7 @@ replay_revstart_v2(svn_revnum_t revision
   SVN_ERR(svn_rdump__get_dump_editor_v2(editor, revision,
                                         rb->stdout_stream,
                                         rb->extra_ra_session,
-                                        check_cancel, NULL, pool, pool));
+                                        NULL, check_cancel, NULL, pool, pool));
 
   return SVN_NO_ERROR;
 }
@@ -328,6 +337,8 @@ replay_revend_v2(svn_revnum_t revision,
  * allocated from POOL.  Use CONFIG_DIR and pass USERNAME, PASSWORD,
  * CONFIG_DIR and NO_AUTH_CACHE to initialize the authorization baton.
  * CONFIG_OPTIONS (if not NULL) is a list of configuration overrides.
+ * REPOS_URL is used to fiddle with server-specific configuration
+ * options.
  */
 static svn_error_t *
 init_client_context(svn_client_ctx_t **ctx_p,
@@ -335,13 +346,14 @@ init_client_context(svn_client_ctx_t **c
                     const char *username,
                     const char *password,
                     const char *config_dir,
+                    const char *repos_url,
                     svn_boolean_t no_auth_cache,
                     svn_boolean_t trust_server_cert,
                     apr_array_header_t *config_options,
                     apr_pool_t *pool)
 {
   svn_client_ctx_t *ctx = NULL;
-  svn_config_t *cfg_config;
+  svn_config_t *cfg_config, *cfg_servers;
 
   SVN_ERR(svn_ra_initialize(pool));
 
@@ -357,6 +369,47 @@ init_client_context(svn_client_ctx_t **c
   cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
                             APR_HASH_KEY_STRING);
 
+  /* ### FIXME: This is a hack to work around the fact that our dump
+     ### editor simply can't handle the way ra_serf violates the
+     ### editor v1 drive ordering requirements.
+     ###
+     ### We'll override both the global value and server-specific one
+     ### for the 'http-bulk-updates' and 'http-max-connections'
+     ### options in order to get ra_serf to try a bulk-update if the
+     ### server will allow it, or at least try to limit all its
+     ### auxiliary GETs/PROPFINDs to happening (well-ordered) on a
+     ### single server connection.
+     ### 
+     ### See http://subversion.tigris.org/issues/show_bug.cgi?id=4116.
+  */
+  cfg_servers = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_SERVERS,
+                             APR_HASH_KEY_STRING);
+  svn_config_set_bool(cfg_servers, SVN_CONFIG_SECTION_GLOBAL,
+                      SVN_CONFIG_OPTION_HTTP_BULK_UPDATES, TRUE);
+  svn_config_set_int64(cfg_servers, SVN_CONFIG_SECTION_GLOBAL,
+                       SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS, 2);
+  if (cfg_servers)
+    {
+      apr_status_t status;
+      apr_uri_t parsed_url;
+
+      status = apr_uri_parse(pool, repos_url, &parsed_url);
+      if (! status)
+        {
+          const char *server_group;
+
+          server_group = svn_config_find_group(cfg_servers, parsed_url.hostname,
+                                               SVN_CONFIG_SECTION_GROUPS, pool);
+          if (server_group)
+            {
+              svn_config_set_bool(cfg_servers, server_group,
+                                  SVN_CONFIG_OPTION_HTTP_BULK_UPDATES, TRUE);
+              svn_config_set_int64(cfg_servers, server_group,
+                                   SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS, 2);
+            }
+        }
+    }
+
   /* Set up our cancellation support. */
   ctx->cancel_func = check_cancel;
 
@@ -413,16 +466,68 @@ dump_revision_header(svn_ra_session_t *s
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+dump_initial_full_revision(svn_ra_session_t *session,
+                           svn_ra_session_t *extra_ra_session,
+                           svn_stream_t *stdout_stream,
+                           svn_revnum_t revision,
+                           svn_boolean_t quiet,
+                           apr_pool_t *pool)
+{
+  const svn_ra_reporter3_t *reporter;
+  void *report_baton;
+  const svn_delta_editor_t *dump_editor;
+  void *dump_baton;
+  const char *session_url, *source_relpath;
+
+  /* Determine whether we're dumping the repository root URL or some
+     child thereof.  If we're dumping a subtree of the repository
+     rather than the root, we have to jump through some hoops to make
+     our update-driven dump generation work the way a replay-driven
+     one would.
+
+     See http://subversion.tigris.org/issues/show_bug.cgi?id=4101
+  */
+  SVN_ERR(svn_ra_get_session_url(session, &session_url, pool));
+  SVN_ERR(svn_ra_get_path_relative_to_root(session, &source_relpath,
+                                           session_url, pool));
+
+  /* Start with a revision record header. */
+  SVN_ERR(dump_revision_header(session, stdout_stream, revision, pool));
+
+  /* Then, we'll drive the dump editor with what would look like a
+     full checkout of the repository as it looked in START_REVISION.
+     We do this by manufacturing a basic 'report' to the update
+     reporter, telling it that we have nothing to start with.  The
+     delta between nothing and everything-at-REV is, effectively, a
+     full dump of REV. */
+  SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton, revision,
+                                     stdout_stream, extra_ra_session,
+                                     source_relpath, check_cancel, NULL, pool));
+  SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton, revision,
+                            "", svn_depth_infinity, FALSE,
+                            dump_editor, dump_baton, pool));
+  SVN_ERR(reporter->set_path(report_baton, "", revision,
+                             svn_depth_infinity, TRUE, NULL, pool));
+  SVN_ERR(reporter->finish_report(report_baton, pool));
+
+  /* All finished with START_REVISION! */
+  if (! quiet)
+    SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+                                revision));
+
+  return SVN_NO_ERROR;
+}
+
 /* Replay revisions START_REVISION thru END_REVISION (inclusive) of
- * the repository located at URL, using callbacks which generate
- * Subversion repository dumpstreams describing the changes made in
- * those revisions.  If QUIET is set, don't generate progress
- * messages.
+ * the repository URL at which SESSION is rooted, using callbacks
+ * which generate Subversion repository dumpstreams describing the
+ * changes made in those revisions.  If QUIET is set, don't generate
+ * progress messages.
  */
 static svn_error_t *
 replay_revisions(svn_ra_session_t *session,
                  svn_ra_session_t *extra_ra_session,
-                 const char *url,
                  svn_revnum_t start_revision,
                  svn_revnum_t end_revision,
                  svn_boolean_t quiet,
@@ -465,7 +570,18 @@ replay_revisions(svn_ra_session_t *sessi
       incremental = TRUE;
     }
 
-  if (incremental)
+  /* If what remains to be dumped is not going to be dumped
+     incrementally, then dump the first revision in full. */
+  if (!incremental)
+    {
+      SVN_ERR(dump_initial_full_revision(session, extra_ra_session,
+                                         stdout_stream, start_revision,
+                                         quiet, pool));
+      start_revision++;
+    }
+
+  /* If there are still revisions left to be dumped, do so. */
+  if (start_revision <= end_revision)
     {
 #ifndef USE_EV2_IMPL
       SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
@@ -478,54 +594,6 @@ replay_revisions(svn_ra_session_t *sessi
                                        NULL, NULL, NULL, NULL, pool));
 #endif
     }
-  else
-    {
-      const svn_ra_reporter3_t *reporter;
-      void *report_baton;
-      const svn_delta_editor_t *dump_editor;
-      void *dump_baton;
-
-      /* First, we need to dump the start_revision in full.  We'll
-         start with a revision record header. */
-      SVN_ERR(dump_revision_header(session, stdout_stream,
-                                   start_revision, pool));
-
-      /* Then, we'll drive the dump editor with what would look like a
-         full checkout of the repository as it looked in
-         START_REVISION.  We do this by manufacturing a basic 'report'
-         to the update reporter, telling it that we have nothing to
-         start with.  The delta between nothing and everything-at-REV
-         is, effectively, a full dump of REV. */
-      SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton,
-                                         start_revision,
-                                         stdout_stream, extra_ra_session,
-                                         check_cancel, NULL, pool));
-      SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
-                                start_revision, "", svn_depth_infinity,
-                                FALSE, dump_editor, dump_baton, pool));
-      SVN_ERR(reporter->set_path(report_baton, "", start_revision,
-                                 svn_depth_infinity, TRUE, NULL, pool));
-      SVN_ERR(reporter->finish_report(report_baton, pool));
-
-      /* All finished with START_REVISION! */
-      if (! quiet)
-        SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
-                                    start_revision));
-      start_revision++;
-
-      /* Now go pick up additional revisions in the range, if any. */
-      if (start_revision <= end_revision)
-#ifndef USE_EV2_IMPL
-        SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
-                                    0, TRUE, replay_revstart, replay_revend,
-                                    replay_baton, pool));
-#else
-      SVN_ERR(svn_ra__replay_range_ev2(session, start_revision, end_revision,
-                                       0, TRUE, replay_revstart_v2,
-                                       replay_revend_v2, replay_baton,
-                                       NULL, NULL, NULL, NULL, pool));
-#endif
-    }
 
   SVN_ERR(svn_stream_close(stdout_stream));
   return SVN_NO_ERROR;
@@ -635,7 +703,6 @@ dump_cmd(apr_getopt_t *os,
   SVN_ERR(svn_ra_reparent(extra_ra_session, repos_root, pool));
 
   return replay_revisions(opt_baton->session, extra_ra_session,
-                          opt_baton->url,
                           opt_baton->start_revision.value.number,
                           opt_baton->end_revision.value.number,
                           opt_baton->quiet, opt_baton->incremental, pool);
@@ -780,6 +847,7 @@ main(int argc, const char **argv)
   svn_boolean_t no_auth_cache = FALSE;
   svn_boolean_t trust_server_cert = FALSE;
   svn_boolean_t non_interactive = FALSE;
+  svn_boolean_t force_interactive = FALSE;
   apr_array_header_t *config_options = NULL;
   apr_getopt_t *os;
   const char *first_arg;
@@ -898,6 +966,9 @@ main(int argc, const char **argv)
         case opt_non_interactive:
           non_interactive = TRUE;
           break;
+        case opt_force_interactive:
+          force_interactive = TRUE;
+          break;
         case opt_incremental:
           opt_baton->incremental = TRUE;
           break;
@@ -916,6 +987,19 @@ main(int argc, const char **argv)
         }
     }
 
+  /* The --non-interactive and --force-interactive options are mutually
+   * exclusive. */
+  if (non_interactive && force_interactive)
+    {
+      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("--non-interactive and --force-interactive "
+                               "are mutually exclusive"));
+      return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
+    }
+  else
+    non_interactive = !svn_cmdline__be_interactive(non_interactive,
+                                                   force_interactive);
+
   if (opt_baton->help)
     {
       subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table,
@@ -1050,6 +1134,7 @@ main(int argc, const char **argv)
                                    username,
                                    password,
                                    config_dir,
+                                   opt_baton->url,
                                    no_auth_cache,
                                    trust_server_cert,
                                    config_options,