subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1549081 [11/18] - in /subversion/branches/invoke-diff-cmd-feature: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/server-side/ contrib/server-side/svncutter/ subversion/bindings/javahl/native/ subversion/bin...
Date Sun, 08 Dec 2013 17:56:53 GMT
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc-queries.sql Sun Dec  8 17:56:46 2013
@@ -125,8 +125,9 @@ WHERE wc_id = ?1 AND local_relpath = ?2
 -- STMT_SELECT_NODE_CHILDREN_INFO
 /* Getting rows in an advantageous order using
      ORDER BY local_relpath, op_depth DESC
-   turns out to be slower than getting rows in a random order and making the
-   C code handle it. */
+   doesn't work as the index is created without the DESC keyword.
+   Using both local_relpath and op_depth descending does work without any
+   performance penalty. */
 SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision,
   checksum, translated_size, changed_revision, changed_date, changed_author,
   depth, symlink_target, last_mod_time, properties, lock_token, lock_owner,
@@ -135,6 +136,7 @@ FROM nodes
 LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
   AND nodes.repos_path = lock.repos_relpath AND op_depth = 0
 WHERE wc_id = ?1 AND parent_relpath = ?2
+ORDER BY local_relpath DESC, op_depth DESC
 
 -- STMT_SELECT_NODE_CHILDREN_WALKER_INFO
 SELECT local_relpath, op_depth, presence, kind
@@ -248,7 +250,7 @@ WHERE wc_id = ?1 
   AND op_depth > ?3
 
 -- STMT_SELECT_LOCAL_RELPATH_OP_DEPTH
-SELECT local_relpath
+SELECT local_relpath, kind
 FROM nodes
 WHERE wc_id = ?1
   AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
@@ -424,6 +426,12 @@ LEFT OUTER JOIN nodes AS moved 
 WHERE work.wc_id = ?1 AND work.local_relpath = ?2 AND work.op_depth > 0
 LIMIT 1
 
+-- STMT_SELECT_MOVED_TO_NODE
+SELECT op_depth, moved_to
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2 AND moved_to IS NOT NULL
+ORDER BY op_depth DESC
+
 -- STMT_SELECT_OP_DEPTH_MOVED_TO
 SELECT n.op_depth, n.moved_to, p.repos_path, p.revision
 FROM nodes p

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.c Sun Dec  8 17:56:46 2013
@@ -1440,6 +1440,15 @@ does_node_exist(svn_boolean_t *exists,
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
+svn_error_t *
+svn_wc__db_install_schema_statistics(svn_sqlite__db_t *sdb,
+                                     apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_INSTALL_SCHEMA_STATISTICS));
+
+  return SVN_NO_ERROR;
+}
+
 /* Helper for create_db(). Initializes our wc.db schema.
  */
 static svn_error_t *
@@ -1467,6 +1476,8 @@ init_db(/* output values */
   SVN_ERR(create_repos_id(repos_id, repos_root_url, repos_uuid,
                           db, scratch_pool));
 
+  SVN_ERR(svn_wc__db_install_schema_statistics(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));
@@ -1484,7 +1495,7 @@ init_db(/* output values */
                                 *wc_id,              /* 1 */
                                 "",                  /* 2 */
                                 0,                   /* op_depth is 0 for base */
-                                NULL,                /* 4 */
+                                SVN_VA_NULL,         /* 4 */
                                 *repos_id,
                                 root_node_repos_relpath,
                                 root_node_revision,
@@ -2604,17 +2615,21 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(svn_wc__db_base_get_info_internal(status, kind, revision,
+  SVN_WC__DB_WITH_TXN4(
+          svn_wc__db_base_get_info_internal(status, kind, revision,
                                             repos_relpath, &repos_id,
                                             changed_rev, changed_date,
                                             changed_author, depth,
                                             checksum, target, lock,
                                             had_props, props, update_root,
                                             wcroot, local_relpath,
-                                            result_pool, scratch_pool));
+                                            result_pool, scratch_pool),
+          svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
+                                      wcroot->sdb, repos_id, result_pool),
+          SVN_NO_ERROR,
+          SVN_NO_ERROR,
+          wcroot);
   SVN_ERR_ASSERT(repos_id != INVALID_REPOS_ID);
-  SVN_ERR(svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool));
 
   return SVN_NO_ERROR;
 }
@@ -8704,19 +8719,22 @@ svn_wc__db_read_info(svn_wc__db_status_t
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(read_info(status, kind, revision, repos_relpath, &repos_id,
+  SVN_WC__DB_WITH_TXN4(
+          read_info(status, kind, revision, repos_relpath, &repos_id,
                     changed_rev, changed_date, changed_author,
                     depth, checksum, target, original_repos_relpath,
                     &original_repos_id, original_revision, lock,
                     recorded_size, recorded_time, changelist, conflicted,
                     op_root, have_props, props_mod,
                     have_base, have_more_work, have_work,
-                    wcroot, local_relpath, result_pool, scratch_pool));
-  SVN_ERR(svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool));
-  SVN_ERR(svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
+                    wcroot, local_relpath, result_pool, scratch_pool),
+          svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
+                                      wcroot->sdb, repos_id, result_pool),
+          svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
                                       wcroot->sdb, original_repos_id,
-                                      result_pool));
+                                      result_pool),
+        SVN_NO_ERROR,
+        wcroot);
 
   return SVN_NO_ERROR;
 }
@@ -8736,6 +8754,7 @@ struct read_children_info_item_t
   int nr_layers;
 };
 
+/* Implementation of svn_wc__db_read_children_info */
 static svn_error_t *
 read_children_info(svn_wc__db_wcroot_t *wcroot,
                    const char *dir_relpath,
@@ -8749,6 +8768,7 @@ read_children_info(svn_wc__db_wcroot_t *
   const char *repos_root_url = NULL;
   const char *repos_uuid = NULL;
   apr_int64_t last_repos_id = INVALID_REPOS_ID;
+  const char *last_repos_root_url = NULL;
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_NODE_CHILDREN_INFO));
@@ -8813,8 +8833,6 @@ read_children_info(svn_wc__db_wcroot_t *
             }
           else
             {
-              const char *last_repos_root_url = NULL;
-
               apr_int64_t repos_id = svn_sqlite__column_int64(stmt, 1);
               if (!repos_root_url ||
                   (last_repos_id != INVALID_REPOS_ID &&
@@ -8864,8 +8882,14 @@ read_children_info(svn_wc__db_wcroot_t *
               child->depth = svn_sqlite__column_token_null(stmt, 11, depth_map,
                                                            svn_depth_unknown);
               if (new_child)
-                SVN_ERR(is_wclocked(&child->locked, wcroot, child_relpath,
-                                    scratch_pool));
+                {
+                  err = is_wclocked(&child->locked, wcroot, child_relpath,
+                                    scratch_pool);
+
+                  if (err)
+                    SVN_ERR(svn_error_compose_create(err,
+                                                     svn_sqlite__reset(stmt)));
+                }
             }
 
           child->recorded_time = svn_sqlite__column_int64(stmt, 13);
@@ -8891,7 +8915,11 @@ read_children_info(svn_wc__db_wcroot_t *
           else
             child->op_root = (op_depth == relpath_depth(child_relpath));
 
-          svn_hash_sets(nodes, apr_pstrdup(result_pool, name), child);
+          if (op_depth && child->op_root)
+            child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20);
+
+          if (new_child)
+            svn_hash_sets(nodes, apr_pstrdup(result_pool, name), child);
         }
 
       if (op_depth == 0)
@@ -8913,18 +8941,40 @@ read_children_info(svn_wc__db_wcroot_t *
           child_item->nr_layers++;
           child_item->info.have_more_work = (child_item->nr_layers > 1);
 
-          /* Moved-to can only exist at op_depth > 0. */
-          /* ### Should we really do this for every layer where op_depth > 0
-                 in undefined order? */
+
+          /* A local_relpath can be moved multiple times at different op
+             depths and it really depends on the caller what is interesting.
+             We provide a simple linked list with the moved_from information */
+
           moved_to_relpath = svn_sqlite__column_text(stmt, 21, NULL);
           if (moved_to_relpath)
-            child_item->info.moved_to_abspath =
-              svn_dirent_join(wcroot->abspath, moved_to_relpath, result_pool);
+            {
+              struct svn_wc__db_moved_to_info_t *moved_to;
+              struct svn_wc__db_moved_to_info_t **next;
+              const char *shadow_op_relpath;
+
+              moved_to = apr_pcalloc(result_pool, sizeof(*moved_to));
+              moved_to->moved_to_abspath = svn_dirent_join(wcroot->abspath,
+                                                           moved_to_relpath,
+                                                           result_pool);
+
+              shadow_op_relpath = svn_relpath_limit(child_relpath, op_depth,
+                                                    scratch_pool);
 
-          /* Moved-here can only exist at op_depth > 0. */
-          /* ### Should we really do this for every layer where op_depth > 0
-                 in undefined order? */
-          child_item->info.moved_here = svn_sqlite__column_boolean(stmt, 20);
+              moved_to->shadow_op_root_abspath =
+                        svn_dirent_join(wcroot->abspath, shadow_op_relpath,
+                                        result_pool);
+
+              next = &child_item->info.moved_to;
+
+              while (*next &&
+                     0 < strcmp((*next)->shadow_op_root_abspath,
+                                moved_to->shadow_op_root_abspath))
+                next = &((*next)->next);
+
+              moved_to->next = *next;
+              *next = moved_to;
+            }
         }
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -9012,6 +9062,175 @@ svn_wc__db_read_children_info(apr_hash_t
   return SVN_NO_ERROR;
 }
 
+/* Implementation of svn_wc__db_read_single_info.
+
+   ### This function is very similar to a lot of code inside
+   read_children_info, but that performs some tricks to re-use data between
+   different siblings.
+
+   ### We read the same few NODES records a few times via different helper
+   functions, so this could be optimized bit, but everything is within
+   a sqlite transaction and all queries are backed by an index, so generally
+   everything (including the used indexes) should be in the sqlite page cache
+   after the first query.
+*/
+static svn_error_t *
+read_single_info(const struct svn_wc__db_info_t **info,
+                 svn_wc__db_wcroot_t *wcroot,
+                 const char *local_relpath,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  struct svn_wc__db_info_t *mtb;
+  apr_int64_t repos_id;
+  const svn_checksum_t *checksum;
+  const char *original_repos_relpath;
+  svn_boolean_t have_work;
+
+  mtb = apr_pcalloc(result_pool, sizeof(*mtb));
+
+  SVN_ERR(read_info(&mtb->status, &mtb->kind, &mtb->revnum,
+                    &mtb->repos_relpath, &repos_id, &mtb->changed_rev,
+                    &mtb->changed_date, &mtb->changed_author, &mtb->depth,
+                    &checksum, NULL, &original_repos_relpath, NULL, NULL,
+                    &mtb->lock, &mtb->recorded_size, &mtb->recorded_time,
+                    &mtb->changelist, &mtb->conflicted, &mtb->op_root,
+                    &mtb->had_props, &mtb->props_mod, &mtb->have_base,
+                    &mtb->have_more_work, &have_work,
+                    wcroot, local_relpath,
+                    result_pool, scratch_pool));
+
+  /* Query the same rows in the database again for move information */
+  if (have_work && (mtb->have_base || mtb->have_more_work))
+    {
+      svn_sqlite__stmt_t *stmt;
+      svn_boolean_t have_row;
+
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_SELECT_MOVED_TO_NODE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+      while (have_row)
+        {
+          struct svn_wc__db_moved_to_info_t *move;
+          int op_depth = svn_sqlite__column_int(stmt, 0);
+          const char *moved_to_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+          const char *cur_relpath;
+
+          move = apr_pcalloc(result_pool, sizeof(*move));
+          move->moved_to_abspath = svn_dirent_join(wcroot->abspath,
+                                                   moved_to_relpath,
+                                                   result_pool);
+
+          cur_relpath = svn_relpath_limit(local_relpath, op_depth,
+                                          scratch_pool);
+
+          move->shadow_op_root_abspath = svn_dirent_join(wcroot->abspath,
+                                                         cur_relpath,
+                                                         result_pool);
+
+          move->next = mtb->moved_to;
+          mtb->moved_to = move;
+
+          SVN_ERR(svn_sqlite__step(&have_row, stmt));
+        }
+
+      SVN_ERR(svn_sqlite__reset(stmt));
+    }
+
+  /* Maybe we have to get some shadowed lock from BASE to make our test suite
+     happy... (It might be completely unrelated, but...)
+     This queries the same BASE row again, joined to the lock table */
+  if (mtb->have_base && (have_work || mtb->kind == svn_node_file))
+    {
+      svn_boolean_t update_root;
+      svn_wc__db_lock_t **lock_arg = NULL;
+
+      if (have_work)
+        lock_arg = &mtb->lock;
+
+      SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL, NULL, NULL,
+                                                NULL, NULL, NULL, NULL, NULL,
+                                                NULL, lock_arg, NULL, NULL,
+                                                &update_root,
+                                                wcroot, local_relpath,
+                                                result_pool, scratch_pool));
+
+      mtb->file_external = (update_root && mtb->kind == svn_node_file);
+    }
+
+  if (mtb->status == svn_wc__db_status_added)
+    {
+      svn_wc__db_status_t status;
+
+      SVN_ERR(scan_addition(&status, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                            NULL, NULL,
+                            wcroot, local_relpath,
+                            result_pool, scratch_pool));
+
+      mtb->moved_here = (status == svn_wc__db_status_moved_here);
+      mtb->incomplete = (status == svn_wc__db_status_incomplete);
+    }
+
+#ifdef HAVE_SYMLINK
+  if (mtb->kind == svn_node_file
+      && (mtb->had_props || mtb->props_mod))
+    {
+      apr_hash_t *properties;
+
+      if (mtb->props_mod)
+        SVN_ERR(svn_wc__db_read_props_internal(&properties,
+                                               wcroot, local_relpath,
+                                               scratch_pool, scratch_pool));
+      else
+        SVN_ERR(db_read_pristine_props(&properties, wcroot, local_relpath,
+                                       TRUE /* deleted_ok */,
+                                       scratch_pool, scratch_pool));
+
+      mtb->special = (NULL != svn_hash_gets(properties, SVN_PROP_SPECIAL));
+    }
+#endif
+
+  mtb->has_checksum = (checksum != NULL);
+  mtb->copied = (original_repos_relpath != NULL);
+
+  SVN_ERR(svn_wc__db_fetch_repos_info(&mtb->repos_root_url, &mtb->repos_uuid,
+                                      wcroot->sdb, repos_id, result_pool));
+
+  if (mtb->kind == svn_node_dir)
+    SVN_ERR(is_wclocked(&mtb->locked, wcroot, local_relpath, scratch_pool));
+
+  *info = mtb;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_read_single_info(const struct svn_wc__db_info_t **info,
+                            svn_wc__db_t *db,
+                            const char *local_abspath,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                                                local_abspath,
+                                                scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_WC__DB_WITH_TXN(read_single_info(info, wcroot, local_relpath,
+                                       result_pool, scratch_pool),
+                      wcroot);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__db_read_pristine_info(svn_wc__db_status_t *status,
                               svn_node_kind_t *kind,
@@ -10483,71 +10702,22 @@ svn_wc__db_read_children(const apr_array
 }
 
 
-/* */
+/* Implementation of svn_wc__db_global_relocate */
 static svn_error_t *
 relocate_txn(svn_wc__db_wcroot_t *wcroot,
              const char *local_relpath,
              const char *repos_root_url,
-             const char *repos_uuid,
-             svn_boolean_t have_base_node,
-             apr_int64_t old_repos_id,
              apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   apr_int64_t new_repos_id;
-
-  /* This function affects all the children of the given local_relpath,
-     but the way that it does this is through the repos inheritance mechanism.
-     So, we only need to rewrite the repos_id of the given local_relpath,
-     as well as any children with a non-null repos_id, as well as various
-     repos_id fields in the locks and working_node tables.
-   */
-
-  /* Get the repos_id for the new repository. */
-  SVN_ERR(create_repos_id(&new_repos_id, repos_root_url, repos_uuid,
-                          wcroot->sdb, scratch_pool));
-
-  /* Set the (base and working) repos_ids and clear the dav_caches */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_RECURSIVE_UPDATE_NODE_REPO));
-  SVN_ERR(svn_sqlite__bindf(stmt, "isii", wcroot->wc_id, local_relpath,
-                            old_repos_id, new_repos_id));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-
-  if (have_base_node)
-    {
-      /* Update any locks for the root or its children. */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_UPDATE_LOCK_REPOS_ID));
-      SVN_ERR(svn_sqlite__bindf(stmt, "ii", old_repos_id, new_repos_id));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_global_relocate(svn_wc__db_t *db,
-                           const char *local_dir_abspath,
-                           const char *repos_root_url,
-                           apr_pool_t *scratch_pool)
-{
-  svn_wc__db_wcroot_t *wcroot;
-  const char *local_relpath;
   const char *local_dir_relpath;
   svn_wc__db_status_t status;
   const char *repos_uuid;
   svn_boolean_t have_base_node;
   apr_int64_t old_repos_id;
 
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
-  /* ### assert that we were passed a directory?  */
-
-  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_dir_relpath,
-                           db, local_dir_abspath, scratch_pool, scratch_pool));
-  VERIFY_USABLE_WCROOT(wcroot);
-  local_relpath = local_dir_relpath;
+  local_dir_relpath = local_relpath;
 
   SVN_ERR(read_info(&status,
                     NULL, NULL, NULL, &old_repos_id,
@@ -10620,13 +10790,60 @@ svn_wc__db_global_relocate(svn_wc__db_t 
 
   SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot->sdb,
                                       old_repos_id, scratch_pool));
-  SVN_ERR_ASSERT(repos_uuid);
+  SVN_ERR_ASSERT(repos_uuid);  /* This function affects all the children of the given local_relpath,
+     but the way that it does this is through the repos inheritance mechanism.
+     So, we only need to rewrite the repos_id of the given local_relpath,
+     as well as any children with a non-null repos_id, as well as various
+     repos_id fields in the locks and working_node tables.
+   */
+
+  /* Get the repos_id for the new repository. */
+  SVN_ERR(create_repos_id(&new_repos_id, repos_root_url, repos_uuid,
+                          wcroot->sdb, scratch_pool));
+
+  /* Set the (base and working) repos_ids and clear the dav_caches */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_RECURSIVE_UPDATE_NODE_REPO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isii", wcroot->wc_id, local_relpath,
+                            old_repos_id, new_repos_id));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  if (have_base_node)
+    {
+      /* Update any locks for the root or its children. */
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_UPDATE_LOCK_REPOS_ID));
+      SVN_ERR(svn_sqlite__bindf(stmt, "ii", old_repos_id, new_repos_id));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_global_relocate(svn_wc__db_t *db,
+                           const char *local_dir_abspath,
+                           const char *repos_root_url,
+                           apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_dir_abspath));
+  /* ### assert that we were passed a directory?  */
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+                           db, local_dir_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
 
   SVN_WC__DB_WITH_TXN(
-    relocate_txn(wcroot, local_relpath, repos_root_url, repos_uuid,
-                 have_base_node, old_repos_id, scratch_pool),
+    relocate_txn(wcroot, local_relpath, repos_root_url, scratch_pool),
     wcroot);
 
+  SVN_ERR(flush_entries(wcroot, local_dir_abspath, svn_depth_infinity,
+                        scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -11408,6 +11625,7 @@ bump_revisions_post_update(svn_wc__db_wc
                            svn_revnum_t new_revision,
                            apr_hash_t *exclude_relpaths,
                            apr_hash_t *wcroot_iprops,
+                           svn_boolean_t empty_update,
                            svn_wc_notify_func2_t notify_func,
                            void *notify_baton,
                            apr_pool_t *scratch_pool)
@@ -11459,6 +11677,7 @@ bump_revisions_post_update(svn_wc__db_wc
                              TRUE /* is_root */, FALSE, db,
                              scratch_pool));
 
+  /* ### TODO: Use empty_update flag for change knowledge */
   SVN_ERR(svn_wc__db_bump_moved_away(wcroot, local_relpath, depth, db,
                                      scratch_pool));
 
@@ -11479,6 +11698,7 @@ svn_wc__db_op_bump_revisions_post_update
                                          svn_revnum_t new_revision,
                                          apr_hash_t *exclude_relpaths,
                                          apr_hash_t *wcroot_iprops,
+                                         svn_boolean_t empty_update,
                                          svn_wc_notify_func2_t notify_func,
                                          void *notify_baton,
                                          apr_pool_t *scratch_pool)
@@ -11501,7 +11721,7 @@ svn_wc__db_op_bump_revisions_post_update
     bump_revisions_post_update(wcroot, local_relpath, db,
                                depth, new_repos_relpath, new_repos_root_url,
                                new_repos_uuid, new_revision,
-                               exclude_relpaths, wcroot_iprops,
+                               exclude_relpaths, wcroot_iprops, empty_update,
                                notify_func, notify_baton, scratch_pool),
     wcroot);
 
@@ -11756,23 +11976,26 @@ get_moved_from_info(const char **moved_f
   return SVN_NO_ERROR;
 }
 
-/* The body of scan_addition().
- */
+/* Like svn_wc__db_scan_addition(), but with WCROOT+LOCAL_RELPATH instead of
+   DB+LOCAL_ABSPATH.
+
+   The output value of *ORIGINAL_REPOS_ID will be INVALID_REPOS_ID if there
+   is no 'copy-from' repository.  */
 static svn_error_t *
-scan_addition_txn(svn_wc__db_status_t *status,
-                  const char **op_root_relpath_p,
-                  const char **repos_relpath,
-                  apr_int64_t *repos_id,
-                  const char **original_repos_relpath,
-                  apr_int64_t *original_repos_id,
-                  svn_revnum_t *original_revision,
-                  const char **moved_from_relpath,
-                  const char **moved_from_op_root_relpath,
-                  int *moved_from_op_depth,
-                  svn_wc__db_wcroot_t *wcroot,
-                  const char *local_relpath,
-                  apr_pool_t *result_pool,
-                  apr_pool_t *scratch_pool)
+scan_addition(svn_wc__db_status_t *status,
+              const char **op_root_relpath_p,
+              const char **repos_relpath,
+              apr_int64_t *repos_id,
+              const char **original_repos_relpath,
+              apr_int64_t *original_repos_id,
+              svn_revnum_t *original_revision,
+              const char **moved_from_relpath,
+              const char **moved_from_op_root_relpath,
+              int *moved_from_op_depth,
+              svn_wc__db_wcroot_t *wcroot,
+              const char *local_relpath,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
 {
   const char *op_root_relpath;
   const char *build_relpath = "";
@@ -11801,8 +12024,7 @@ scan_addition_txn(svn_wc__db_status_t *s
     svn_boolean_t have_row;
     svn_wc__db_status_t presence;
     int op_depth;
-    const char *repos_prefix_path = "";
-    int i;
+    const char *repos_prefix_path;
 
     /* ### is it faster to fetch fewer columns? */
     SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -11851,17 +12073,9 @@ scan_addition_txn(svn_wc__db_status_t *s
 
 
     /* Calculate the op root local path components */
-    op_root_relpath = local_relpath;
-
-    for (i = relpath_depth(local_relpath); i > op_depth; --i)
-      {
-        /* Calculate the path of the operation root */
-        repos_prefix_path =
-          svn_relpath_join(svn_relpath_basename(op_root_relpath, NULL),
-                           repos_prefix_path,
-                           scratch_pool);
-        op_root_relpath = svn_relpath_dirname(op_root_relpath, scratch_pool);
-      }
+    op_root_relpath = svn_relpath_limit(local_relpath, op_depth, scratch_pool);
+    repos_prefix_path = svn_relpath_skip_ancestor(op_root_relpath,
+                                                  local_relpath);
 
     if (op_root_relpath_p)
       *op_root_relpath_p = apr_pstrdup(result_pool, op_root_relpath);
@@ -11955,6 +12169,7 @@ scan_addition_txn(svn_wc__db_status_t *s
 
     while (TRUE)
       {
+        const char *tmp;
 
         SVN_ERR(svn_sqlite__reset(stmt));
 
@@ -11975,16 +12190,13 @@ scan_addition_txn(svn_wc__db_status_t *s
         op_depth = svn_sqlite__column_int(stmt, 0);
 
         /* Skip to op_depth */
-        for (i = relpath_depth(op_root_relpath); i > op_depth; i--)
-          {
-            /* Calculate the path of the operation root */
-            repos_prefix_path =
-              svn_relpath_join(svn_relpath_basename(op_root_relpath, NULL),
-                               repos_prefix_path,
-                               scratch_pool);
-            op_root_relpath =
-              svn_relpath_dirname(op_root_relpath, scratch_pool);
-          }
+        tmp = op_root_relpath;
+
+        op_root_relpath = svn_relpath_limit(op_root_relpath, op_depth,
+                                              scratch_pool);
+        repos_prefix_path = svn_relpath_join(
+                              svn_relpath_skip_ancestor(op_root_relpath, tmp),
+                              repos_prefix_path, scratch_pool);
       }
 
       SVN_ERR(svn_sqlite__reset(stmt));
@@ -12045,39 +12257,6 @@ scan_addition_txn(svn_wc__db_status_t *s
   return SVN_NO_ERROR;
 }
 
-
-/* Like svn_wc__db_scan_addition(), but with WCROOT+LOCAL_RELPATH instead of
-   DB+LOCAL_ABSPATH.
-
-   The output value of *ORIGINAL_REPOS_ID will be INVALID_REPOS_ID if there
-   is no 'copy-from' repository.  */
-static svn_error_t *
-scan_addition(svn_wc__db_status_t *status,
-              const char **op_root_relpath,
-              const char **repos_relpath,
-              apr_int64_t *repos_id,
-              const char **original_repos_relpath,
-              apr_int64_t *original_repos_id,
-              svn_revnum_t *original_revision,
-              const char **moved_from_relpath,
-              const char **moved_from_op_root_relpath,
-              int *moved_from_op_depth,
-              svn_wc__db_wcroot_t *wcroot,
-              const char *local_relpath,
-              apr_pool_t *result_pool,
-              apr_pool_t *scratch_pool)
-{
-  SVN_WC__DB_WITH_TXN(
-    scan_addition_txn(status, op_root_relpath, repos_relpath, repos_id,
-                      original_repos_relpath, original_repos_id,
-                      original_revision, moved_from_relpath,
-                      moved_from_op_root_relpath, moved_from_op_depth,
-                      wcroot, local_relpath, result_pool, scratch_pool),
-    wcroot);
-  return SVN_NO_ERROR;
-}
-
-
 svn_error_t *
 svn_wc__db_scan_addition(svn_wc__db_status_t *status,
                          const char **op_root_abspath,
@@ -12109,7 +12288,8 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(scan_addition(status,
+  SVN_WC__DB_WITH_TXN(
+          scan_addition(status,
                         op_root_abspath
                                 ? &op_root_relpath
                                 : NULL,
@@ -12117,7 +12297,8 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                         original_repos_relpath, original_repos_id_p,
                         original_revision,
                         NULL, NULL, NULL,
-                        wcroot, local_relpath, result_pool, scratch_pool));
+                        wcroot, local_relpath, result_pool, scratch_pool),
+          wcroot);
 
   if (op_root_abspath)
     *op_root_abspath = svn_dirent_join(wcroot->abspath, op_root_relpath,
@@ -12158,7 +12339,8 @@ svn_wc__db_scan_moved(const char **moved
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(scan_addition(&status,
+  SVN_WC__DB_WITH_TXN(
+          scan_addition(&status,
                         op_root_abspath
                                 ? &op_root_relpath
                                 : NULL,
@@ -12174,7 +12356,8 @@ svn_wc__db_scan_moved(const char **moved
                         moved_from_delete_abspath
                             ? &moved_from_op_depth
                             : NULL,
-                        wcroot, local_relpath, scratch_pool, scratch_pool));
+                        wcroot, local_relpath, scratch_pool, scratch_pool),
+          wcroot);
 
   if (status != svn_wc__db_status_moved_here || !moved_from_relpath)
     return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
@@ -12198,12 +12381,8 @@ svn_wc__db_scan_moved(const char **moved
   /* The deleted node is either where we moved from, or one of its ancestors */
   if (moved_from_delete_abspath)
     {
-      const char *tmp = moved_from_op_root_relpath;
-
-      SVN_ERR_ASSERT(moved_from_op_depth >= 0);
-
-      while (relpath_depth(tmp) > moved_from_op_depth)
-        tmp = svn_relpath_dirname(tmp, scratch_pool);
+      const char *tmp = svn_relpath_limit(moved_from_op_root_relpath,
+                                          moved_from_op_depth, scratch_pool);
 
       *moved_from_delete_abspath = svn_dirent_join(wcroot->abspath, tmp,
                                                    scratch_pool);
@@ -12382,9 +12561,9 @@ svn_wc__db_op_depth_moved_to(const char 
         = svn_relpath_join(*move_dst_op_root_relpath,
                            svn_relpath_skip_ancestor(relpath, local_relpath),
                            result_pool);
-      while (delete_op_depth < relpath_depth(relpath))
-        relpath = svn_relpath_dirname(relpath, scratch_pool);
-      *move_src_op_root_relpath = apr_pstrdup(result_pool, relpath);
+
+      *move_src_op_root_relpath = svn_relpath_limit(relpath, delete_op_depth,
+                                                    result_pool);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db.h Sun Dec  8 17:56:46 2013
@@ -1909,6 +1909,16 @@ svn_wc__db_read_info(svn_wc__db_status_t
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool);
 
+/* Structure used as linked list in svn_wc__db_info_t to describe all nodes
+   in this location that were moved to another location */
+struct svn_wc__db_moved_to_info_t
+{
+  const char *moved_to_abspath;
+  const char *shadow_op_root_abspath;
+
+  struct svn_wc__db_moved_to_info_t *next;
+};
+
 /* Structure returned by svn_wc__db_read_children_info.  Only has the
    fields needed by status. */
 struct svn_wc__db_info_t {
@@ -1945,7 +1955,10 @@ struct svn_wc__db_info_t {
   svn_wc__db_lock_t *lock;  /* Repository file lock */
   svn_boolean_t incomplete; /* TRUE if a working node is incomplete */
 
-  const char *moved_to_abspath; /* Only on op-roots. See svn_wc_status3_t. */
+  struct svn_wc__db_moved_to_info_t *moved_to; /* A linked list of locations
+                                                 where nodes at this path
+                                                 are moved to. Highest layers
+                                                 first */
   svn_boolean_t moved_here;     /* Only on op-roots. */
 
   svn_boolean_t file_external;
@@ -1967,6 +1980,14 @@ svn_wc__db_read_children_info(apr_hash_t
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
 
+/* Like svn_wc__db_read_children_info, but only gets an info node for the root
+   element. */
+svn_error_t *
+svn_wc__db_read_single_info(const struct svn_wc__db_info_t **info,
+                            svn_wc__db_t *db,
+                            const char *local_abspath,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
 
 /* Structure returned by svn_wc__db_read_walker_info.  Only has the
    fields needed by svn_wc__internal_walk_children(). */
@@ -2518,6 +2539,9 @@ svn_wc__db_global_update(svn_wc__db_t *d
    for pathnames contained in EXCLUDE_RELPATHS are not touched by this
    function.  These pathnames should be paths relative to the wcroot.
 
+   If EMPTY_UPDATE is TRUE then no nodes at or below LOCAL_ABSPATH have been
+   affected by the update/switch yet.
+
    If WCROOT_IPROPS is not NULL it is a hash mapping const char * absolute
    working copy paths to depth-first ordered arrays of
    svn_prop_inherited_item_t * structures.  If LOCAL_ABSPATH exists in
@@ -2534,6 +2558,7 @@ svn_wc__db_op_bump_revisions_post_update
                                          svn_revnum_t new_revision,
                                          apr_hash_t *exclude_relpaths,
                                          apr_hash_t *wcroot_iprops,
+                                         svn_boolean_t empty_update,
                                          svn_wc_notify_func2_t notify_func,
                                          void *notify_baton,
                                          apr_pool_t *scratch_pool);
@@ -2685,7 +2710,8 @@ svn_wc__db_scan_addition(svn_wc__db_stat
                          apr_pool_t *scratch_pool);
 
 /* Scan the working copy for move information of the node LOCAL_ABSPATH.
- * If LOCAL_ABSPATH return a SVN_ERR_WC_PATH_UNEXPECTED_STATUS error.
+ * If LOCAL_ABSPATH is not moved here return an
+ * SVN_ERR_WC_PATH_UNEXPECTED_STATUS error.
  *
  * If not NULL *MOVED_FROM_ABSPATH will be set to the previous location
  * of LOCAL_ABSPATH, before it or an ancestror was moved.
@@ -2831,6 +2857,16 @@ svn_wc__db_scan_deletion(const char **ba
    @{
 */
 
+/* Installs or updates Sqlite schema statistics for the current (aka latest)
+   working copy schema.
+
+   This function should be called once on initializing the database and after
+   an schema update completes */
+svn_error_t *
+svn_wc__db_install_schema_statistics(svn_sqlite__db_t *sdb,
+                                     apr_pool_t *scratch_pool);
+
+
 /* Create a new wc.db file for LOCAL_DIR_ABSPATH, which is going to be a
    working copy for the repository REPOS_ROOT_URL with uuid REPOS_UUID.
    Return the raw sqlite handle, repository id and working copy id

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_private.h Sun Dec  8 17:56:46 2013
@@ -361,6 +361,18 @@ svn_wc__db_with_txn(svn_wc__db_wcroot_t 
   SVN_SQLITE__WITH_LOCK(expr, (wcroot)->sdb)
 
 
+/* Evaluate the expressions EXPR1..EXPR4 within a transaction, returning the
+ * first error if an error occurs.
+ *
+ * Begin a transaction in WCROOT's DB; evaluate the expressions, which would
+ * typically be  function calls that do some work in DB; finally commit
+ * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
+ * the transaction.
+ */
+#define SVN_WC__DB_WITH_TXN4(expr1, expr2, expr3, expr4, wcroot) \
+  SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, (wcroot)->sdb)
+
+
 /* Return CHILDREN mapping const char * names to svn_node_kind_t * for the
    children of LOCAL_RELPATH at OP_DEPTH. */
 svn_error_t *

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c Sun Dec  8 17:56:46 2013
@@ -1627,6 +1627,7 @@ replace_moved_layer(const char *src_relp
       svn_error_t *err;
       svn_sqlite__stmt_t *stmt2;
       const char *src_cp_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map);
       const char *dst_cp_relpath
         = svn_relpath_join(dst_relpath,
                            svn_relpath_skip_ancestor(src_relpath,
@@ -1643,6 +1644,11 @@ replace_moved_layer(const char *src_relp
                                                     scratch_pool));
       if (!err)
         err = svn_sqlite__step_done(stmt2);
+
+      if (!err && strlen(dst_cp_relpath) > strlen(dst_relpath))
+        err = svn_wc__db_extend_parent_delete(wcroot, dst_cp_relpath, kind,
+                                              dst_op_depth, scratch_pool);
+
       if (err)
         return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_util.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_util.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_util.c Sun Dec  8 17:56:46 2013
@@ -136,22 +136,6 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
                                  svn_dirent_local_style(sdb_abspath,
                                                         scratch_pool));
     }
-#ifndef WIN32
-  else
-    {
-      apr_file_t *f;
-
-      /* A standard SQLite build creates a DB with mode 644 ^ !umask
-         which means the file doesn't have group/world write access
-         even when umask allows it. By ensuring the file exists before
-         SQLite gets involved we give it the permissions allowed by
-         umask. */
-      SVN_ERR(svn_io_file_open(&f, sdb_abspath,
-                               (APR_READ | APR_WRITE | APR_CREATE),
-                               APR_OS_DEFAULT, scratch_pool));
-      SVN_ERR(svn_io_file_close(f, scratch_pool));
-    }
-#endif
 
   SVN_ERR(svn_sqlite__open(sdb, sdb_abspath, smode,
                            my_statements ? my_statements : statements,

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c Sun Dec  8 17:56:46 2013
@@ -132,7 +132,7 @@ AuthzSVNAccessFile_cmd(cmd_parms *cmd, v
 
   conf->access_file = canonicalize_access_file(arg1, TRUE, cmd->pool);
   if (!conf->access_file)
-    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, NULL);
+    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, SVN_VA_NULL);
 
   return NULL;
 }
@@ -153,7 +153,7 @@ AuthzSVNReposRelativeAccessFile_cmd(cmd_
                                                              cmd->pool);
 
   if (!conf->repo_relative_access_file)
-    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, NULL);
+    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, SVN_VA_NULL);
 
   return NULL;
 }
@@ -166,7 +166,7 @@ AuthzSVNGroupsFile_cmd(cmd_parms *cmd, v
   conf->groups_file = canonicalize_access_file(arg1, TRUE, cmd->pool);
 
   if (!conf->groups_file)
-    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, NULL);
+    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, SVN_VA_NULL);
 
   return NULL;
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h Sun Dec  8 17:56:46 2013
@@ -52,8 +52,11 @@ extern "C" {
 /* a pool-key for the shared dav_svn_root used by autoversioning  */
 #define DAV_SVN__AUTOVERSIONING_ACTIVITY "svn-autoversioning-activity"
 
-/* Option values for SVNAllowBulkUpdates */
+/* Option values for SVNAllowBulkUpdates.  Note that
+   it's important that CONF_BULKUPD_DEFAULT is 0 to make
+   dav_svn_merge_dir_config do the right thing. */
 typedef enum dav_svn__bulk_upd_conf {
+    CONF_BULKUPD_DEFAULT,
     CONF_BULKUPD_ON,
     CONF_BULKUPD_OFF,
     CONF_BULKUPD_PREFER

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/lock.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/lock.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/lock.c Sun Dec  8 17:56:46 2013
@@ -274,8 +274,13 @@ parse_locktoken(apr_pool_t *pool,
 static const char *
 format_locktoken(apr_pool_t *p, const dav_locktoken *locktoken)
 {
-  /* libsvn_fs already produces a valid locktoken URI. */
-  return apr_pstrdup(p, locktoken->uuid_str);
+  svn_stringbuf_t *formatted
+    = svn_stringbuf_create_ensure(strlen(locktoken->uuid_str), p);
+
+  /* libsvn_fs produces a locktoken URI that will be valid XML when
+     escaped. */
+  svn_xml_escape_cdata_cstring(&formatted, locktoken->uuid_str, p);
+  return formatted->data;
 }
 
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c Sun Dec  8 17:56:46 2013
@@ -214,10 +214,10 @@ create_dir_config(apr_pool_t *p, char *d
      <Location /blah> directive. So we treat it as a urlpath. */
   if (dir)
     conf->root_dir = svn_urlpath__canonicalize(dir, p);
-  conf->bulk_updates = CONF_BULKUPD_ON;
-  conf->v2_protocol = CONF_FLAG_ON;
+  conf->bulk_updates = CONF_BULKUPD_DEFAULT;
+  conf->v2_protocol = CONF_FLAG_DEFAULT;
   conf->hooks_env = NULL;
-  conf->txdelta_cache = CONF_FLAG_ON;
+  conf->txdelta_cache = CONF_FLAG_DEFAULT;
 
   return conf;
 }
@@ -613,6 +613,16 @@ SVNHooksEnv_cmd(cmd_parms *cmd, void *co
   return NULL;
 }
 
+static svn_boolean_t
+get_conf_flag(enum conf_flag flag, svn_boolean_t default_value)
+{
+  if (flag == CONF_FLAG_ON)
+    return TRUE;
+  else if (flag == CONF_FLAG_OFF)
+    return FALSE;
+  else /* CONF_FLAG_DEFAULT*/
+    return default_value;
+}
 
 /** Accessor functions for the module's configuration state **/
 
@@ -813,7 +823,12 @@ dav_svn__get_bulk_updates_flag(request_r
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->bulk_updates;
+
+  /* SVNAllowBulkUpdates is 'on' by default. */
+  if (conf->bulk_updates == CONF_BULKUPD_DEFAULT)
+    return CONF_BULKUPD_ON;
+  else
+    return conf->bulk_updates;
 }
 
 
@@ -824,7 +839,7 @@ dav_svn__check_httpv2_support(request_re
   svn_boolean_t available;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  available = conf->v2_protocol == CONF_FLAG_ON;
+  available = get_conf_flag(conf->v2_protocol, TRUE);
 
   /* If our configuration says that HTTPv2 is available, but we are
      proxying requests to a master Subversion server which lacks
@@ -907,7 +922,9 @@ dav_svn__get_txdelta_cache_flag(request_
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->txdelta_cache == CONF_FLAG_ON;
+
+  /* txdelta caching is enabled by default. */
+  return get_conf_flag(conf->txdelta_cache, TRUE);
 }
 
 
@@ -1097,7 +1114,8 @@ static int dav_svn__handler(request_rec 
 
 /* Fill the filename on the request with a bogus path since we aren't serving
  * a file off the disk.  This means that <Directory> blocks will not match and
- * that %f in logging formats will show as "svn:/path/to/repo/path/in/repo". */
+ * %f in logging formats will show as "dav_svn:/path/to/repo/path/in/repo".
+ */
 static int dav_svn__translate_name(request_rec *r)
 {
   const char *fs_path, *repos_basename, *repos_path;
@@ -1146,7 +1164,7 @@ static int dav_svn__translate_name(reque
   if (repos_path && '/' == repos_path[0] && '\0' == repos_path[1])
     repos_path = NULL;
 
-  /* Combine 'svn:', fs_path and repos_path to produce the bogus path we're
+  /* Combine 'dav_svn:', fs_path and repos_path to produce the bogus path we're
    * placing in r->filename.  We can't use our standard join helpers such
    * as svn_dirent_join.  fs_path is a dirent and repos_path is a fspath
    * (that can be trivially converted to a relpath by skipping the leading
@@ -1154,7 +1172,7 @@ static int dav_svn__translate_name(reque
    * repository is 'trunk/c:hi' this results in a non canonical dirent on
    * Windows. Instead we just cat them together. */
   r->filename = apr_pstrcat(r->pool,
-                            "svn:", fs_path, repos_path, SVN_VA_NULL);
+                            "dav_svn:", fs_path, repos_path, SVN_VA_NULL);
 
   /* Leave a note to ourselves so that we know not to decline in the
    * map_to_storage hook. */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/reports/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/reports/update.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/reports/update.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/reports/update.c Sun Dec  8 17:56:46 2013
@@ -934,7 +934,7 @@ validate_input_revision(svn_revnum_t rev
                         const dav_resource *resource)
 {
   if (! SVN_IS_VALID_REVNUM(revision))
-    return SVN_NO_ERROR;
+    return NULL;
 
   if (revision > youngest)
     {
@@ -958,7 +958,7 @@ validate_input_revision(svn_revnum_t rev
                                   "Invalid revision found in update report "
                                   "request.", resource->pool);
     }
-  return SVN_NO_ERROR;
+  return NULL;
 }
 
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c Sun Dec  8 17:56:46 2013
@@ -2159,7 +2159,7 @@ get_resource(request_rec *r,
       svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                     dav_svn__get_fulltext_cache_flag(r) ? "1" :"0");
       svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                    dav_svn__get_revprop_cache_flag(r) ? "1" :"0");
+                    dav_svn__get_revprop_cache_flag(r) ? "2" :"0");
 
       /* Disallow BDB/event until issue 4157 is fixed. */
       if (!strcmp(ap_show_mpm(), "event"))
@@ -2191,9 +2191,16 @@ get_resource(request_rec *r,
              leak that path back to the client, because that would be
              a security risk, but we do want to log the real error on
              the server side. */
-          return dav_svn__sanitize_error(serr, "Could not open the requested "
-                                         "SVN filesystem",
-                                         HTTP_INTERNAL_SERVER_ERROR, r);
+
+          apr_status_t cause = svn_error_root_cause(serr)->apr_err;
+          if (APR_STATUS_IS_ENOENT(cause) || APR_STATUS_IS_ENOTDIR(cause))
+            return dav_svn__sanitize_error(
+                serr, "Could not find the requested SVN filesystem",
+                HTTP_NOT_FOUND, r);
+          else
+            return dav_svn__sanitize_error(
+                serr, "Could not open the requested SVN filesystem",
+                HTTP_INTERNAL_SERVER_ERROR, r);
         }
 
       /* Cache the open repos for the next request on this connection */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/add-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/add-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/add-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/add-cmd.c Sun Dec  8 17:56:46 2013
@@ -83,7 +83,7 @@ svn_cl__add(apr_getopt_t *os,
                errors, opt_state->quiet,
                SVN_ERR_ENTRY_EXISTS,
                SVN_ERR_WC_PATH_NOT_FOUND,
-               SVN_NO_ERROR));
+               0));
     }
 
   svn_pool_destroy(iterpool);

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/blame-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/blame-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/blame-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/blame-cmd.c Sun Dec  8 17:56:46 2013
@@ -74,7 +74,7 @@ blame_receiver_xml(void *baton,
                         "line-number",
                         apr_psprintf(pool, "%" APR_INT64_T_FMT,
                                      line_no + 1),
-                        NULL);
+                        SVN_VA_NULL);
 
   if (SVN_IS_VALID_REVNUM(revision))
     svn_cl__print_xml_commit(&sb, revision,
@@ -88,7 +88,7 @@ blame_receiver_xml(void *baton,
     {
       /* "<merged>" */
       svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "merged",
-                            "path", merged_path, NULL);
+                            "path", merged_path, SVN_VA_NULL);
 
       svn_cl__print_xml_commit(&sb, merged_revision,
                              svn_prop_get_value(merged_rev_props,
@@ -350,7 +350,7 @@ svn_cl__blame(apr_getopt_t *os,
           if (! svn_path_is_url(target))
             outpath = svn_dirent_local_style(truepath, subpool);
           svn_xml_make_open_tag(&bl.sbuf, pool, svn_xml_normal, "target",
-                                "path", outpath, NULL);
+                                "path", outpath, SVN_VA_NULL);
 
           receiver = blame_receiver_xml;
         }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/cat-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/cat-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/cat-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/cat-cmd.c Sun Dec  8 17:56:46 2013
@@ -76,15 +76,16 @@ svn_cl__cat(apr_getopt_t *os,
       SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                  subpool));
 
-      SVN_ERR(svn_cl__try(svn_client_cat2(out, truepath, &peg_revision,
+      SVN_ERR(svn_cl__try(svn_client_cat3(NULL, out, truepath, &peg_revision,
                                           &(opt_state->start_revision),
-                                          ctx, subpool),
+                                          !opt_state->ignore_keywords,
+                                          ctx, subpool, subpool),
                            errors, opt_state->quiet,
                            SVN_ERR_UNVERSIONED_RESOURCE,
                            SVN_ERR_ENTRY_NOT_FOUND,
                            SVN_ERR_CLIENT_IS_DIRECTORY,
                            SVN_ERR_FS_NOT_FOUND,
-                           SVN_NO_ERROR));
+                           0));
     }
   svn_pool_destroy(subpool);
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/changelist-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/changelist-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/changelist-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/changelist-cmd.c Sun Dec  8 17:56:46 2013
@@ -106,7 +106,7 @@ svn_cl__changelist(apr_getopt_t *os,
                errors, opt_state->quiet,
                SVN_ERR_UNVERSIONED_RESOURCE,
                SVN_ERR_WC_PATH_NOT_FOUND,
-               SVN_NO_ERROR));
+               0));
     }
   else
     {
@@ -117,7 +117,7 @@ svn_cl__changelist(apr_getopt_t *os,
                errors, opt_state->quiet,
                SVN_ERR_UNVERSIONED_RESOURCE,
                SVN_ERR_WC_PATH_NOT_FOUND,
-               SVN_NO_ERROR));
+               0));
     }
 
   if (errors->nelts > 0)

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/cl.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/cl.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/cl.h Sun Dec  8 17:56:46 2013
@@ -322,7 +322,7 @@ extern const apr_getopt_option_t svn_cl_
  *
  * Typically, error codes like SVN_ERR_UNVERSIONED_RESOURCE,
  * SVN_ERR_ENTRY_NOT_FOUND, etc, are supplied in varargs.  Don't
- * forget to terminate the argument list with SVN_NO_ERROR.
+ * forget to terminate the argument list with 0 (or APR_SUCCESS).
  */
 svn_error_t *
 svn_cl__try(svn_error_t *err,

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/cleanup-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/cleanup-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/cleanup-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/cleanup-cmd.c Sun Dec  8 17:56:46 2013
@@ -47,7 +47,7 @@ svn_cl__cleanup(apr_getopt_t *os,
   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
   int i;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
@@ -61,43 +61,60 @@ svn_cl__cleanup(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
 
-  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(pool);
   for (i = 0; i < targets->nelts; i++)
     {
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
-      svn_error_t *err;
+      const char *target_abspath;
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
       SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
-      err = svn_client_cleanup2(target, opt_state->include_externals,
-                                opt_state->remove_unversioned,
-                                opt_state->remove_ignored,
-                                ctx, subpool);
-      if (err && err->apr_err == SVN_ERR_WC_LOCKED)
+
+      SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, iterpool));
+
+      if (opt_state->remove_unversioned || opt_state->remove_ignored)
         {
-          const char *target_abspath;
-          svn_error_t *err2 = svn_dirent_get_absolute(&target_abspath,
-                                                      target, subpool);
-          if (err2)
-            {
-              err =  svn_error_compose_create(err, err2);
-            }
-          else if (opt_state->remove_unversioned || opt_state->remove_ignored)
-            {
-              err = svn_error_create(SVN_ERR_WC_LOCKED, err,
+          svn_error_t *err = svn_client_vacuum(target_abspath,
+                                               opt_state->remove_unversioned,
+                                               opt_state->remove_ignored,
+                                               TRUE /* fix_timestamps */,
+                                               FALSE /* vacuum_pristines */,
+                                               opt_state->include_externals,
+                                               ctx, iterpool);
+
+          if (err && err->apr_err == SVN_ERR_WC_LOCKED)
+            err = svn_error_create(SVN_ERR_WC_LOCKED, err,
                                      _("Working copy locked; if no other "
                                        "Subversion client is currently "
                                        "using the working copy, try running "
                                        "'svn cleanup' without the "
                                        "--remove-unversioned and "
                                        "--remove-ignored options first."));
-            }
-          else
+          else if (err && err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY)
+            err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+                                     _("Cannot remove unversioned or ignored "
+                                       "items from something that is not a "
+                                       "working copy"));
+
+          SVN_ERR(err);
+        }
+      else
+        {
+          svn_error_t *err = svn_client_cleanup2(target_abspath,
+                                                 TRUE /* break_locks */,
+                                                 TRUE /* fix_timestamps */,
+                                                 TRUE /* clear_dav_cache */,
+                                                 TRUE /* vacuum_pristines */,
+                                                 opt_state->include_externals,
+                                                 ctx, iterpool);
+
+          if (err && err->apr_err == SVN_ERR_WC_LOCKED)
             {
               const char *wcroot_abspath;
+              svn_error_t *err2;
 
               err2 = svn_client_get_wc_root(&wcroot_abspath, target_abspath,
-                                            ctx, subpool, subpool);
+                                            ctx, iterpool, iterpool);
               if (err2)
                 err =  svn_error_compose_create(err, err2);
               else
@@ -106,20 +123,12 @@ svn_cl__cleanup(apr_getopt_t *os,
                                           "'svn cleanup' on the root of the "
                                           "working copy ('%s') instead."),
                                           svn_dirent_local_style(wcroot_abspath,
-                                                                 subpool));
+                                                                 iterpool));
             }
+          SVN_ERR(err);
         }
-      else if (err && err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY &&
-               (opt_state->remove_unversioned || opt_state->remove_ignored))
-        {
-          err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, err,
-                                 _("Cannot remove unversioned or ignored "
-                                   "items from something that is not a "
-                                   "working copy"));
-        }
-      SVN_ERR(err);
     }
 
-  svn_pool_destroy(subpool);
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/diff-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/diff-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/diff-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/diff-cmd.c Sun Dec  8 17:56:46 2013
@@ -117,7 +117,7 @@ summarize_xml(const svn_client_diff_summ
                         "kind", svn_cl__node_kind_str_xml(summary->node_kind),
                         "item", kind_to_word(summary->summarize_kind),
                         "props", summary->prop_changed ? "modified" : "none",
-                        NULL);
+                        SVN_VA_NULL);
 
   svn_xml_escape_cdata_cstring(&sb, path, pool);
   svn_xml_make_close_tag(&sb, pool, "path");
@@ -212,7 +212,7 @@ svn_cl__diff(apr_getopt_t *os,
       SVN_ERR(svn_cl__xml_print_header("diff", pool));
 
       sb = svn_stringbuf_create_empty(pool);
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", SVN_VA_NULL);
       SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
     }
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/info-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/info-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/info-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/info-cmd.c Sun Dec  8 17:56:46 2013
@@ -100,7 +100,7 @@ print_info_xml(void *baton,
                                   path_prefix, target, pool),
                         "kind", svn_cl__node_kind_str_xml(info->kind),
                         "revision", rev_str,
-                        NULL);
+                        SVN_VA_NULL);
 
   /* "<url> xx </url>" */
   svn_cl__xml_tagged_cdata(&sb, pool, "url", info->URL);
@@ -121,7 +121,8 @@ print_info_xml(void *baton,
   if (info->repos_root_URL || info->repos_UUID)
     {
       /* "<repository>" */
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository",
+                            SVN_VA_NULL);
 
       /* "<root> xx </root>" */
       svn_cl__xml_tagged_cdata(&sb, pool, "root", info->repos_root_URL);
@@ -136,7 +137,8 @@ print_info_xml(void *baton,
   if (info->wc_info)
     {
       /* "<wc-info>" */
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info",
+                            SVN_VA_NULL);
 
       /* "<wcroot-abspath> xx </wcroot-abspath>" */
       if (info->wc_info->wcroot_abspath)

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/list-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/list-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/list-cmd.c Sun Dec  8 17:56:46 2013
@@ -213,7 +213,7 @@ print_dirent_xml(void *baton,
           svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal, "external",
                                 "parent_url", external_parent_url,
                                 "target", external_target,
-                                NULL);
+                                SVN_VA_NULL);
 
           pb->last_external_parent_url = external_parent_url;
           pb->last_external_target = external_target;
@@ -223,7 +223,7 @@ print_dirent_xml(void *baton,
 
   svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal, "entry",
                         "kind", svn_cl__node_kind_str_xml(dirent->kind),
-                        NULL);
+                        SVN_VA_NULL);
 
   svn_cl__xml_tagged_cdata(&sb, scratch_pool, "name", entryname);
 
@@ -237,7 +237,7 @@ print_dirent_xml(void *baton,
   svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal, "commit",
                         "revision",
                         apr_psprintf(scratch_pool, "%ld", dirent->created_rev),
-                        NULL);
+                        SVN_VA_NULL);
   svn_cl__xml_tagged_cdata(&sb, scratch_pool, "author", dirent->last_author);
   if (dirent->time)
     svn_cl__xml_tagged_cdata(&sb, scratch_pool, "date",
@@ -246,7 +246,8 @@ print_dirent_xml(void *baton,
 
   if (lock)
     {
-      svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal, "lock", NULL);
+      svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal, "lock",
+                            SVN_VA_NULL);
       svn_cl__xml_tagged_cdata(&sb, scratch_pool, "token", lock->token);
       svn_cl__xml_tagged_cdata(&sb, scratch_pool, "owner", lock->owner);
       svn_cl__xml_tagged_cdata(&sb, scratch_pool, "comment", lock->comment);
@@ -359,7 +360,7 @@ svn_cl__list(apr_getopt_t *os,
           svn_stringbuf_t *sb = svn_stringbuf_create_empty(pool);
           svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "list",
                                 "path", truepath[0] == '\0' ? "." : truepath,
-                                NULL);
+                                SVN_VA_NULL);
           SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
         }
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svn/log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svn/log-cmd.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svn/log-cmd.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svn/log-cmd.c Sun Dec  8 17:56:46 2013
@@ -39,52 +39,13 @@
 #include "private/svn_cmdline_private.h"
 
 #include "cl.h"
+#include "cl-log.h"
 
 #include "svn_private_config.h"
 
 
 /*** Code. ***/
 
-/* Baton for log_entry_receiver() and log_entry_receiver_xml(). */
-struct log_receiver_baton
-{
-  /* Client context. */
-  svn_client_ctx_t *ctx;
-
-  /* The target of the log operation. */
-  const char *target_path_or_url;
-  svn_opt_revision_t target_peg_revision;
-
-  /* Don't print log message body nor its line count. */
-  svn_boolean_t omit_log_message;
-
-  /* Whether to show diffs in the log. (maps to --diff) */
-  svn_boolean_t show_diff;
-
-  /* Depth applied to diff output. */
-  svn_depth_t depth;
-
-  /* Diff arguments received from command line. */
-  const char *diff_extensions;
-
-  /* Custom diff command. */
-  const char *invoke_diff_cmd;
-
-  /* Stack which keeps track of merge revision nesting, using svn_revnum_t's */
-  apr_array_header_t *merge_stack;
-
-  /* Log message search patterns. Log entries will only be shown if the author,
-   * the log message, or a changed path matches one of these patterns. */
-  apr_array_header_t *search_patterns;
-
-  /* Pool for persistent allocations. */
-  apr_pool_t *pool;
-};
-
-
-/* The separator between log messages. */
-#define SEP_STRING \
-  "------------------------------------------------------------------------\n"
 
 
 /* Display a diff of the subtree TARGET_PATH_OR_URL@TARGET_PEG_REVISION as
@@ -254,7 +215,7 @@ match_search_patterns(apr_array_header_t
 /* Implement `svn_log_entry_receiver_t', printing the logs in
  * a human-readable and machine-parseable format.
  *
- * BATON is of type `struct log_receiver_baton'.
+ * BATON is of type `svn_cl__log_receiver_baton'.
  *
  * First, print a header line.  Then if CHANGED_PATHS is non-null,
  * print all affected paths in a list headed "Changed paths:\n",
@@ -328,12 +289,12 @@ match_search_patterns(apr_array_header_t
  * ------------------------------------------------------------------------
  *
  */
-static svn_error_t *
-log_entry_receiver(void *baton,
-                   svn_log_entry_t *log_entry,
-                   apr_pool_t *pool)
+svn_error_t *
+svn_cl__log_entry_receiver(void *baton,
+                           svn_log_entry_t *log_entry,
+                           apr_pool_t *pool)
 {
-  struct log_receiver_baton *lb = baton;
+  svn_cl__log_receiver_baton *lb = baton;
   const char *author;
   const char *date;
   const char *message;
@@ -348,7 +309,9 @@ log_entry_receiver(void *baton,
 
   if (! SVN_IS_VALID_REVNUM(log_entry->revision))
     {
-      apr_array_pop(lb->merge_stack);
+      if (lb->merge_stack)
+        apr_array_pop(lb->merge_stack);
+
       return SVN_NO_ERROR;
     }
 
@@ -372,13 +335,18 @@ log_entry_receiver(void *baton,
                               log_entry->changed_paths2, pool))
     {
       if (log_entry->has_children)
-        APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+        {
+          if (! lb->merge_stack)
+            lb->merge_stack = apr_array_make(lb->pool, 1, sizeof(svn_revnum_t));
+
+          APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+        }
 
       return SVN_NO_ERROR;
     }
 
   SVN_ERR(svn_cmdline_printf(pool,
-                             SEP_STRING "r%ld | %s | %s",
+                             SVN_CL__LOG_SEP_STRING "r%ld | %s | %s",
                              log_entry->revision, author, date));
 
   if (message != NULL)
@@ -430,7 +398,7 @@ log_entry_receiver(void *baton,
         }
     }
 
-  if (lb->merge_stack->nelts > 0)
+  if (lb->merge_stack && lb->merge_stack->nelts > 0)
     {
       int i;
 
@@ -479,7 +447,12 @@ log_entry_receiver(void *baton,
     }
 
   if (log_entry->has_children)
-    APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+    {
+      if (! lb->merge_stack)
+        lb->merge_stack = apr_array_make(lb->pool, 1, sizeof(svn_revnum_t));
+
+      APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+    }
 
   return SVN_NO_ERROR;
 }
@@ -487,7 +460,7 @@ log_entry_receiver(void *baton,
 
 /* This implements `svn_log_entry_receiver_t', printing the logs in XML.
  *
- * BATON is of type `struct log_receiver_baton'.
+ * BATON is of type `svn_cl__log_receiver_baton'.
  *
  * Here is an example of the output; note that the "<log>" and
  * "</log>" tags are not emitted by this function:
@@ -521,12 +494,12 @@ log_entry_receiver(void *baton,
  * </log>
  *
  */
-static svn_error_t *
-log_entry_receiver_xml(void *baton,
-                       svn_log_entry_t *log_entry,
-                       apr_pool_t *pool)
+svn_error_t *
+svn_cl__log_entry_receiver_xml(void *baton,
+                               svn_log_entry_t *log_entry,
+                               apr_pool_t *pool)
 {
-  struct log_receiver_baton *lb = baton;
+  svn_cl__log_receiver_baton *lb = baton;
   /* Collate whole log message into sb before printing. */
   svn_stringbuf_t *sb = svn_stringbuf_create_empty(pool);
   char *revstr;
@@ -546,7 +519,8 @@ log_entry_receiver_xml(void *baton,
     {
       svn_xml_make_close_tag(&sb, pool, "logentry");
       SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
-      apr_array_pop(lb->merge_stack);
+      if (lb->merge_stack)
+        apr_array_pop(lb->merge_stack);
 
       return SVN_NO_ERROR;
     }
@@ -557,7 +531,12 @@ log_entry_receiver_xml(void *baton,
                               log_entry->changed_paths2, pool))
     {
       if (log_entry->has_children)
-        APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+        {
+          if (! lb->merge_stack)
+            lb->merge_stack = apr_array_make(lb->pool, 1, sizeof(svn_revnum_t));
+
+          APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+        }
 
       return SVN_NO_ERROR;
     }
@@ -572,7 +551,7 @@ log_entry_receiver_xml(void *baton,
   revstr = apr_psprintf(pool, "%ld", log_entry->revision);
   /* <logentry revision="xxx"> */
   svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "logentry",
-                        "revision", revstr, NULL);
+                        "revision", revstr, SVN_VA_NULL);
 
   /* <author>xxx</author> */
   svn_cl__xml_tagged_cdata(&sb, pool, "author", author);
@@ -593,7 +572,7 @@ log_entry_receiver_xml(void *baton,
 
       /* <paths> */
       svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths",
-                            NULL);
+                            SVN_VA_NULL);
 
       /* Get an array of sorted hash keys. */
       sorted_paths = svn_sort__hash(log_entry->changed_paths2,
@@ -625,7 +604,7 @@ log_entry_receiver_xml(void *baton,
                                                      log_item->text_modified),
                                     "prop-mods", svn_tristate__to_word(
                                                      log_item->props_modified),
-                                    NULL);
+                                    SVN_VA_NULL);
             }
           else
             {
@@ -638,7 +617,7 @@ log_entry_receiver_xml(void *baton,
                                                      log_item->text_modified),
                                     "prop-mods", svn_tristate__to_word(
                                                      log_item->props_modified),
-                                    NULL);
+                                    SVN_VA_NULL);
             }
           /* xxx</path> */
           svn_xml_escape_cdata_cstring(&sb, path, pool);
@@ -658,7 +637,7 @@ log_entry_receiver_xml(void *baton,
   svn_compat_log_revprops_clear(log_entry->revprops);
   if (log_entry->revprops && apr_hash_count(log_entry->revprops) > 0)
     {
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", SVN_VA_NULL);
       SVN_ERR(svn_cmdline__print_xml_prop_hash(&sb, log_entry->revprops,
                                                FALSE, /* name_only */
                                                FALSE, pool));
@@ -666,7 +645,12 @@ log_entry_receiver_xml(void *baton,
     }
 
   if (log_entry->has_children)
-    APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+    {
+      if (! lb->merge_stack)
+        lb->merge_stack = apr_array_make(lb->pool, 1, sizeof(svn_revnum_t));
+
+      APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
+    }
   else
     svn_xml_make_close_tag(&sb, pool, "logentry");
 
@@ -683,7 +667,7 @@ svn_cl__log(apr_getopt_t *os,
   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
-  struct log_receiver_baton lb;
+  svn_cl__log_receiver_baton lb;
   const char *target;
   int i;
   apr_array_header_t *revprops;
@@ -807,8 +791,7 @@ svn_cl__log(apr_getopt_t *os,
   lb.depth = opt_state->depth == svn_depth_unknown ? svn_depth_infinity
                                                    : opt_state->depth;
   lb.diff_extensions = opt_state->extensions;
-  lb.invoke_diff_cmd = opt_state->diff.invoke_diff_cmd;
-  lb.merge_stack = apr_array_make(pool, 0, sizeof(svn_revnum_t));
+  lb.merge_stack = NULL;
   lb.search_patterns = opt_state->search_patterns;
   lb.pool = pool;
 
@@ -863,7 +846,7 @@ svn_cl__log(apr_getopt_t *os,
                               opt_state->use_merge_history,
                               move_behavior,
                               revprops,
-                              log_entry_receiver_xml,
+                              svn_cl__log_entry_receiver_xml,
                               &lb,
                               ctx,
                               pool));
@@ -887,13 +870,13 @@ svn_cl__log(apr_getopt_t *os,
                               opt_state->use_merge_history,
                               move_behavior,
                               revprops,
-                              log_entry_receiver,
+                              svn_cl__log_entry_receiver,
                               &lb,
                               ctx,
                               pool));
 
       if (! opt_state->incremental)
-        SVN_ERR(svn_cmdline_printf(pool, SEP_STRING));
+        SVN_ERR(svn_cmdline_printf(pool, SVN_CL__LOG_SEP_STRING));
     }
 
   return SVN_NO_ERROR;



Mime
View raw message