You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2018/11/07 12:30:11 UTC

svn commit: r1846002 [21/44] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/generator/util/ build/win32/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contr...

Modified: subversion/branches/ra-git/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/upgrade.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/upgrade.c Wed Nov  7 12:30:06 2018
@@ -653,178 +653,6 @@ ensure_repos_info(svn_wc_entry_t *entry,
 }
 
 
-/*
- * Read tree conflict descriptions from @a conflict_data.  Set @a *conflicts
- * to a hash of pointers to svn_wc_conflict_description2_t objects indexed by
- * svn_wc_conflict_description2_t.local_abspath, all newly allocated in @a
- * pool.  @a dir_path is the path to the working copy directory whose conflicts
- * are being read.  The conflicts read are the tree conflicts on the immediate
- * child nodes of @a dir_path.  Do all allocations in @a pool.
- *
- * Note: There were some concerns about this function:
- *
- * ### this is BAD. the CONFLICTS structure should not be dependent upon
- * ### DIR_PATH. each conflict should be labeled with an entry name, not
- * ### a whole path. (and a path which happens to vary based upon invocation
- * ### of the user client and these APIs)
- *
- * those assumptions were baked into former versions of the data model, so
- * they have to stick around here.  But they have been removed from the
- * New Way. */
-static svn_error_t *
-read_tree_conflicts(apr_hash_t **conflicts,
-                    const char *conflict_data,
-                    const char *dir_path,
-                    apr_pool_t *pool)
-{
-  const svn_skel_t *skel;
-  apr_pool_t *iterpool;
-
-  *conflicts = apr_hash_make(pool);
-
-  if (conflict_data == NULL)
-    return SVN_NO_ERROR;
-
-  skel = svn_skel__parse(conflict_data, strlen(conflict_data), pool);
-  if (skel == NULL)
-    return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
-                            _("Error parsing tree conflict skel"));
-
-  iterpool = svn_pool_create(pool);
-  for (skel = skel->children; skel != NULL; skel = skel->next)
-    {
-      const svn_wc_conflict_description2_t *conflict;
-
-      svn_pool_clear(iterpool);
-      SVN_ERR(svn_wc__deserialize_conflict(&conflict, skel, dir_path,
-                                           pool, iterpool));
-      if (conflict != NULL)
-        svn_hash_sets(*conflicts,
-                      svn_dirent_basename(conflict->local_abspath, pool),
-                      conflict);
-    }
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-/* */
-static svn_error_t *
-migrate_single_tree_conflict_data(svn_sqlite__db_t *sdb,
-                                  const char *tree_conflict_data,
-                                  apr_int64_t wc_id,
-                                  const char *local_relpath,
-                                  apr_pool_t *scratch_pool)
-{
-  apr_hash_t *conflicts;
-  apr_hash_index_t *hi;
-  apr_pool_t *iterpool;
-
-  SVN_ERR(read_tree_conflicts(&conflicts, tree_conflict_data, local_relpath,
-                              scratch_pool));
-
-  iterpool = svn_pool_create(scratch_pool);
-  for (hi = apr_hash_first(scratch_pool, conflicts);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const svn_wc_conflict_description2_t *conflict = apr_hash_this_val(hi);
-      const char *conflict_relpath;
-      const char *conflict_data;
-      svn_sqlite__stmt_t *stmt;
-      svn_boolean_t have_row;
-      svn_skel_t *skel;
-
-      svn_pool_clear(iterpool);
-
-      conflict_relpath = svn_dirent_join(local_relpath,
-                                         svn_dirent_basename(
-                                           conflict->local_abspath, iterpool),
-                                         iterpool);
-
-      SVN_ERR(svn_wc__serialize_conflict(&skel, conflict, iterpool, iterpool));
-      conflict_data = svn_skel__unparse(skel, iterpool)->data;
-
-      /* See if we need to update or insert an ACTUAL node. */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ACTUAL_NODE));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, conflict_relpath));
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-      SVN_ERR(svn_sqlite__reset(stmt));
-
-      if (have_row)
-        {
-          /* There is an existing ACTUAL row, so just update it. */
-          SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                            STMT_UPDATE_ACTUAL_CONFLICT));
-        }
-      else
-        {
-          /* We need to insert an ACTUAL row with the tree conflict data. */
-          SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                            STMT_INSERT_ACTUAL_CONFLICT));
-        }
-
-      SVN_ERR(svn_sqlite__bindf(stmt, "iss", wc_id, conflict_relpath,
-                                conflict_data));
-      if (!have_row)
-        SVN_ERR(svn_sqlite__bind_text(stmt, 4, local_relpath));
-
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
-
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-
-/* */
-static svn_error_t *
-migrate_tree_conflict_data(svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
-  /* Iterate over each node which has a set of tree conflicts, then insert
-     all of them into the new schema.  */
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT));
-
-  /* Get all the existing tree conflict data. */
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  while (have_row)
-    {
-      apr_int64_t wc_id;
-      const char *local_relpath;
-      const char *tree_conflict_data;
-
-      svn_pool_clear(iterpool);
-
-      wc_id = svn_sqlite__column_int64(stmt, 0);
-      local_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
-      tree_conflict_data = svn_sqlite__column_text(stmt, 2, iterpool);
-
-      SVN_ERR(migrate_single_tree_conflict_data(sdb, tree_conflict_data,
-                                                wc_id, local_relpath,
-                                                iterpool));
-
-      /* We don't need to do anything but step over the previously
-         prepared statement. */
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  /* Erase all the old tree conflict data.  */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_UPGRADE_21_ERASE_OLD_CONFLICTS));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-
-  svn_pool_destroy(iterpool);
-  return SVN_NO_ERROR;
-}
-
 /* ### need much more docco
 
    ### this function should be called within a sqlite transaction. it makes
@@ -1318,234 +1146,6 @@ migrate_text_bases(apr_hash_t **text_bas
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-bump_to_20(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_NODES));
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_20));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_21(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_21));
-  SVN_ERR(migrate_tree_conflict_data(sdb, scratch_pool));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_22(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_22));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_23(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_UPGRADE_23_HAS_WORKING_NODES));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  SVN_ERR(svn_sqlite__reset(stmt));
-  if (have_row)
-    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                             _("The working copy at '%s' is format 22 with "
-                               "WORKING nodes; use a format 22 client to "
-                               "diff/revert before using this client"),
-                             wcroot_abspath);
-
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_23));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_24(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_24));
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_NODES_TRIGGERS));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_25(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_25));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_26(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_26));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_27(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                  STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  SVN_ERR(svn_sqlite__reset(stmt));
-  if (have_row)
-    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                             _("The working copy at '%s' is format 26 with "
-                               "conflicts; use a format 26 client to resolve "
-                               "before using this client"),
-                             wcroot_abspath);
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_27));
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-bump_to_28(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_28));
-  return SVN_NO_ERROR;
-}
-
-/* If FINFO indicates that ABSPATH names a file, rename it to
- * '<ABSPATH>.svn-base'.
- *
- * Ignore any file whose name is not the expected length, in order to make
- * life easier for any developer who runs this code twice or has some
- * non-standard files in the pristine directory.
- *
- * A callback for bump_to_29(), implementing #svn_io_walk_func_t. */
-static svn_error_t *
-rename_pristine_file(void *baton,
-                     const char *abspath,
-                     const apr_finfo_t *finfo,
-                     apr_pool_t *pool)
-{
-  if (finfo->filetype == APR_REG
-      && (strlen(svn_dirent_basename(abspath, pool))
-          == PRISTINE_BASENAME_OLD_LEN))
-    {
-      const char *new_abspath
-        = apr_pstrcat(pool, abspath, PRISTINE_STORAGE_EXT, SVN_VA_NULL);
-
-      SVN_ERR(svn_io_file_rename2(abspath, new_abspath, FALSE, pool));
-    }
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-upgrade_externals(struct bump_baton *bb,
-                  svn_sqlite__db_t *sdb,
-                  apr_pool_t *scratch_pool)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_sqlite__stmt_t *stmt_add;
-  svn_boolean_t have_row;
-  apr_pool_t *iterpool;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    STMT_SELECT_EXTERNAL_PROPERTIES));
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt_add, sdb,
-                                    STMT_INSERT_EXTERNAL));
-
-  /* ### For this intermediate upgrade we just assume WC_ID = 1.
-     ### Before this bump we lost track of externals all the time,
-     ### so lets keep this easy. */
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", (apr_int64_t)1, ""));
-
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
-  iterpool = svn_pool_create(scratch_pool);
-  while (have_row)
-    {
-      apr_hash_t *props;
-      const char *externals;
-
-      svn_pool_clear(iterpool);
-
-      SVN_ERR(svn_sqlite__column_properties(&props, stmt, 0,
-                                            iterpool, iterpool));
-
-      externals = svn_prop_get_value(props, SVN_PROP_EXTERNALS);
-
-      if (externals)
-        {
-          apr_array_header_t *ext;
-          const char *local_relpath;
-          const char *local_abspath;
-          int i;
-
-          local_relpath = svn_sqlite__column_text(stmt, 1, NULL);
-          local_abspath = svn_dirent_join(bb->wcroot_abspath, local_relpath,
-                                          iterpool);
-
-          SVN_ERR(svn_wc_parse_externals_description3(&ext, local_abspath,
-                                                      externals, FALSE,
-                                                      iterpool));
-
-          for (i = 0; i < ext->nelts; i++)
-            {
-              const svn_wc_external_item2_t *item;
-              const char *item_relpath;
-
-              item = APR_ARRAY_IDX(ext, i, const svn_wc_external_item2_t *);
-              item_relpath = svn_relpath_join(local_relpath, item->target_dir,
-                                              iterpool);
-
-              /* Insert dummy externals definitions: Insert an unknown
-                 external, to make sure it will be cleaned up when it is not
-                 updated on the next update. */
-              SVN_ERR(svn_sqlite__bindf(stmt_add, "isssssis",
-                                        (apr_int64_t)1, /* wc_id */
-                                        item_relpath,
-                                        svn_relpath_dirname(item_relpath,
-                                                            iterpool),
-                                        "normal",
-                                        "unknown",
-                                        local_relpath,
-                                        (apr_int64_t)1, /* repos_id */
-                                        "" /* repos_relpath */));
-              SVN_ERR(svn_sqlite__insert(NULL, stmt_add));
-            }
-        }
-
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
-
-  svn_pool_destroy(iterpool);
-  return svn_error_trace(svn_sqlite__reset(stmt));
-}
-
-static svn_error_t *
-bump_to_29(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  struct bump_baton *bb = baton;
-  const char *wcroot_abspath = bb->wcroot_abspath;
-  const char *pristine_dir_abspath;
-
-  /* Rename all pristine files, adding a ".svn-base" suffix. */
-  pristine_dir_abspath = svn_dirent_join_many(scratch_pool, wcroot_abspath,
-                                              svn_wc_get_adm_dir(scratch_pool),
-                                              PRISTINE_STORAGE_RELPATH,
-                                              SVN_VA_NULL);
-  SVN_ERR(svn_io_dir_walk2(pristine_dir_abspath, APR_FINFO_MIN,
-                           rename_pristine_file, NULL, scratch_pool));
-
-  /* Externals */
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_EXTERNALS));
-
-  SVN_ERR(upgrade_externals(bb, sdb, scratch_pool));
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_29));
-  return SVN_NO_ERROR;
-}
-
 svn_error_t *
 svn_wc__upgrade_conflict_skel_from_raw(svn_skel_t **conflicts,
                                        svn_wc__db_t *db,
@@ -1637,7 +1237,7 @@ svn_wc__upgrade_conflict_skel_from_raw(s
                                                       db, wri_abspath,
                                                       tc->reason,
                                                       tc->action,
-                                                      NULL,
+                                                      NULL, NULL,
                                                       scratch_pool,
                                                       scratch_pool));
 
@@ -1774,41 +1374,10 @@ bump_to_31(void *baton,
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_array_header_t *empty_iprops = apr_array_make(
     scratch_pool, 0, sizeof(svn_prop_inherited_item_t *));
-  svn_boolean_t iprops_column_exists = FALSE;
   svn_error_t *err;
 
-  /* Add the inherited_props column to NODES if it does not yet exist.
-   *
-   * When using a format >= 31 client to upgrade from old formats which
-   * did not yet have a NODES table, the inherited_props column has
-   * already been created as part of the NODES table. Attemping to add
-   * the inherited_props column will raise an error in this case, so check
-   * if the column exists first.
-   *
-   * Checking for the existence of a column before ALTER TABLE is not
-   * possible within SQLite. We need to run a separate query and evaluate
-   * its result in C first.
-   */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_PRAGMA_TABLE_INFO_NODES));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  while (have_row)
-    {
-      const char *column_name = svn_sqlite__column_text(stmt, 1, NULL);
-
-      if (strcmp(column_name, "inherited_props") == 0)
-        {
-          iprops_column_exists = TRUE;
-          break;
-        }
-
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
-  if (!iprops_column_exists)
-    SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31_ALTER_TABLE));
-
   /* Run additional statements to finalize the upgrade to format 31. */
-  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31_FINALIZE));
+  SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31));
 
   /* Set inherited_props to an empty array for the roots of all
      switched subtrees in the WC.  This allows subsequent updates
@@ -2090,6 +1659,15 @@ svn_wc__upgrade_sdb(int *result_format,
                              svn_dirent_local_style(wcroot_abspath,
                                                     scratch_pool),
                              start_format);
+  else if (start_format < 29)
+    return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL,
+                             _("Working copy '%s' is an old development "
+                               "version (format %d); to upgrade it, "
+                               "use a Subversion 1.7-1.9 client, then "
+                               "use the current client"),
+                             svn_dirent_local_style(wcroot_abspath,
+                                                    scratch_pool),
+                             start_format);                             
 
   /* ### need lock-out. only one upgrade at a time. note that other code
      ### cannot use this un-upgraded database until we finish the upgrade.  */
@@ -2098,66 +1676,6 @@ svn_wc__upgrade_sdb(int *result_format,
      intentional. */
   switch (start_format)
     {
-      case 19:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_20, &bb,
-                                             scratch_pool));
-        *result_format = 20;
-        /* FALLTHROUGH  */
-
-      case 20:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_21, &bb,
-                                             scratch_pool));
-        *result_format = 21;
-        /* FALLTHROUGH  */
-
-      case 21:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_22, &bb,
-                                             scratch_pool));
-        *result_format = 22;
-        /* FALLTHROUGH  */
-
-      case 22:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_23, &bb,
-                                             scratch_pool));
-        *result_format = 23;
-        /* FALLTHROUGH  */
-
-      case 23:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_24, &bb,
-                                             scratch_pool));
-        *result_format = 24;
-        /* FALLTHROUGH  */
-
-      case 24:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_25, &bb,
-                                             scratch_pool));
-        *result_format = 25;
-        /* FALLTHROUGH  */
-
-      case 25:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_26, &bb,
-                                             scratch_pool));
-        *result_format = 26;
-        /* FALLTHROUGH  */
-
-      case 26:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_27, &bb,
-                                             scratch_pool));
-        *result_format = 27;
-        /* FALLTHROUGH  */
-
-      case 27:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_28, &bb,
-                                             scratch_pool));
-        *result_format = 28;
-        /* FALLTHROUGH  */
-
-      case 28:
-        SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_29, &bb,
-                                             scratch_pool));
-        *result_format = 29;
-        /* FALLTHROUGH  */
-
       case 29:
         SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_30, &bb,
                                              scratch_pool));

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc-metadata.sql?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc-metadata.sql Wed Nov  7 12:30:06 2018
@@ -229,11 +229,6 @@ CREATE TABLE WC_LOCK (
  );
 
 
-PRAGMA user_version =
--- define: SVN_WC__VERSION
-;
-
-
 /* ------------------------------------------------------------------------- */
 
 /* The NODES table describes the way WORKING nodes are layered on top of
@@ -279,7 +274,6 @@ PRAGMA user_version =
    An 'svn revert foo/bar' would remove the NODES of (2).
 
  */
--- STMT_CREATE_NODES
 CREATE TABLE NODES (
   /* Working copy location related fields */
 
@@ -503,8 +497,6 @@ CREATE VIEW NODES_BASE AS
   SELECT * FROM nodes
   WHERE op_depth = 0;
 
--- STMT_CREATE_NODES_TRIGGERS
-
 CREATE TRIGGER nodes_insert_trigger
 AFTER INSERT ON nodes
 WHEN NEW.checksum IS NOT NULL
@@ -532,8 +524,6 @@ BEGIN
   WHERE checksum = OLD.checksum;
 END;
 
--- STMT_CREATE_EXTERNALS
-
 CREATE TABLE EXTERNALS (
   /* Working copy location related fields (like NODES)*/
 
@@ -572,6 +562,12 @@ CREATE UNIQUE INDEX I_EXTERNALS_DEFINED
                                                       def_local_relpath,
                                                       local_relpath);
 
+
+PRAGMA user_version =
+-- define: SVN_WC__VERSION
+;
+
+
 /* ------------------------------------------------------------------------- */
 /* This statement provides SQLite with the necessary information about our
    indexes to make better decisions in the query planner.
@@ -630,208 +626,6 @@ INSERT INTO sqlite_stat1(tbl, idx, stat)
 ANALYZE sqlite_master; /* Loads sqlite_stat1 data for query optimizer */
 /* ------------------------------------------------------------------------- */
 
-/* Format 20 introduces NODES and removes BASE_NODE and WORKING_NODE */
-
--- STMT_UPGRADE_TO_20
-
-UPDATE BASE_NODE SET checksum = (SELECT checksum FROM pristine
-                                 WHERE md5_checksum = BASE_NODE.checksum)
-WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = BASE_NODE.checksum);
-
-UPDATE WORKING_NODE SET checksum = (SELECT checksum FROM pristine
-                                    WHERE md5_checksum = WORKING_NODE.checksum)
-WHERE EXISTS (SELECT 1 FROM pristine
-              WHERE md5_checksum = WORKING_NODE.checksum);
-
-INSERT INTO NODES (
-       wc_id, local_relpath, op_depth, parent_relpath,
-       repos_id, repos_path, revision,
-       presence, depth, moved_here, moved_to, kind,
-       changed_revision, changed_date, changed_author,
-       checksum, properties, translated_size, last_mod_time,
-       dav_cache, symlink_target, file_external )
-SELECT wc_id, local_relpath, 0 /*op_depth*/, parent_relpath,
-       repos_id, repos_relpath, revnum,
-       presence, depth, NULL /*moved_here*/, NULL /*moved_to*/, kind,
-       changed_rev, changed_date, changed_author,
-       checksum, properties, translated_size, last_mod_time,
-       dav_cache, symlink_target, file_external
-FROM BASE_NODE;
-INSERT INTO NODES (
-       wc_id, local_relpath, op_depth, parent_relpath,
-       repos_id, repos_path, revision,
-       presence, depth, moved_here, moved_to, kind,
-       changed_revision, changed_date, changed_author,
-       checksum, properties, translated_size, last_mod_time,
-       dav_cache, symlink_target, file_external )
-SELECT wc_id, local_relpath, 2 /*op_depth*/, parent_relpath,
-       copyfrom_repos_id, copyfrom_repos_path, copyfrom_revnum,
-       presence, depth, NULL /*moved_here*/, NULL /*moved_to*/, kind,
-       changed_rev, changed_date, changed_author,
-       checksum, properties, translated_size, last_mod_time,
-       NULL /*dav_cache*/, symlink_target, NULL /*file_external*/
-FROM WORKING_NODE;
-
-DROP TABLE BASE_NODE;
-DROP TABLE WORKING_NODE;
-
-PRAGMA user_version = 20;
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 21 involves no schema changes, it moves the tree conflict victim
-   information to victime nodes, rather than parents. */
-
--- STMT_UPGRADE_TO_21
-PRAGMA user_version = 21;
-
-/* For format 21 bump code */
--- STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT
-SELECT wc_id, local_relpath, tree_conflict_data
-FROM actual_node
-WHERE tree_conflict_data IS NOT NULL
-
-/* For format 21 bump code */
--- STMT_UPGRADE_21_ERASE_OLD_CONFLICTS
-UPDATE actual_node SET tree_conflict_data = NULL
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 22 simply moves the tree conflict information from the conflict_data
-   column to the tree_conflict_data column. */
-
--- STMT_UPGRADE_TO_22
-UPDATE actual_node SET tree_conflict_data = conflict_data;
-UPDATE actual_node SET conflict_data = NULL;
-
-PRAGMA user_version = 22;
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 23 involves no schema changes, it introduces multi-layer
-   op-depth processing for NODES. */
-
--- STMT_UPGRADE_TO_23
-PRAGMA user_version = 23;
-
--- STMT_UPGRADE_23_HAS_WORKING_NODES
-SELECT 1 FROM nodes WHERE op_depth > 0
-LIMIT 1
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 24 involves no schema changes; it starts using the pristine
-   table's refcount column correctly. */
-
--- STMT_UPGRADE_TO_24
-UPDATE pristine SET refcount =
-  (SELECT COUNT(*) FROM nodes
-   WHERE checksum = pristine.checksum /*OR checksum = pristine.md5_checksum*/);
-
-PRAGMA user_version = 24;
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 25 introduces the NODES_CURRENT view. */
-
--- STMT_UPGRADE_TO_25
-DROP VIEW IF EXISTS NODES_CURRENT;
-CREATE VIEW NODES_CURRENT AS
-  SELECT * FROM nodes
-    JOIN (SELECT wc_id, local_relpath, MAX(op_depth) AS op_depth FROM nodes
-          GROUP BY wc_id, local_relpath) AS filter
-    ON nodes.wc_id = filter.wc_id
-      AND nodes.local_relpath = filter.local_relpath
-      AND nodes.op_depth = filter.op_depth;
-
-PRAGMA user_version = 25;
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 26 introduces the NODES_BASE view. */
-
--- STMT_UPGRADE_TO_26
-DROP VIEW IF EXISTS NODES_BASE;
-CREATE VIEW NODES_BASE AS
-  SELECT * FROM nodes
-  WHERE op_depth = 0;
-
-PRAGMA user_version = 26;
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 27 involves no schema changes, it introduces stores
-   conflict files as relpaths rather than names in ACTUAL_NODE. */
-
--- STMT_UPGRADE_TO_27
-PRAGMA user_version = 27;
-
-/* For format 27 bump code */
--- STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS
-SELECT 1 FROM actual_node
-WHERE NOT ((prop_reject IS NULL) AND (conflict_old IS NULL)
-           AND (conflict_new IS NULL) AND (conflict_working IS NULL)
-           AND (tree_conflict_data IS NULL))
-LIMIT 1
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 28 involves no schema changes, it only converts MD5 pristine
-   references to SHA1. */
-
--- STMT_UPGRADE_TO_28
-
-UPDATE NODES SET checksum = (SELECT checksum FROM pristine
-                             WHERE md5_checksum = nodes.checksum)
-WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = nodes.checksum);
-
-PRAGMA user_version = 28;
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 29 introduces the EXTERNALS table (See STMT_CREATE_TRIGGERS) and
-   optimizes a few trigger definitions. ... */
-
--- STMT_UPGRADE_TO_29
-
-DROP TRIGGER IF EXISTS nodes_update_checksum_trigger;
-DROP TRIGGER IF EXISTS nodes_insert_trigger;
-DROP TRIGGER IF EXISTS nodes_delete_trigger;
-
-CREATE TRIGGER nodes_update_checksum_trigger
-AFTER UPDATE OF checksum ON nodes
-WHEN NEW.checksum IS NOT OLD.checksum
-  /* AND (NEW.checksum IS NOT NULL OR OLD.checksum IS NOT NULL) */
-BEGIN
-  UPDATE pristine SET refcount = refcount + 1
-  WHERE checksum = NEW.checksum;
-  UPDATE pristine SET refcount = refcount - 1
-  WHERE checksum = OLD.checksum;
-END;
-
-CREATE TRIGGER nodes_insert_trigger
-AFTER INSERT ON nodes
-WHEN NEW.checksum IS NOT NULL
-BEGIN
-  UPDATE pristine SET refcount = refcount + 1
-  WHERE checksum = NEW.checksum;
-END;
-
-CREATE TRIGGER nodes_delete_trigger
-AFTER DELETE ON nodes
-WHEN OLD.checksum IS NOT NULL
-BEGIN
-  UPDATE pristine SET refcount = refcount - 1
-  WHERE checksum = OLD.checksum;
-END;
-
-PRAGMA user_version = 29;
-
-/* ------------------------------------------------------------------------- */
-
 /* Format 30 creates a new NODES index for move information, and a new
    PRISTINE index for the md5_checksum column. It also activates use of
    skel-based conflict storage -- see notes/wc-ng/conflict-storage-2.0.
@@ -870,9 +664,9 @@ WHERE wc_id = ?1 and local_relpath = ?2
 /* Format 31 adds the inherited_props column to the NODES table. C code then
    initializes the update/switch roots to make sure future updates fetch the
    inherited properties */
--- STMT_UPGRADE_TO_31_ALTER_TABLE
+-- STMT_UPGRADE_TO_31
 ALTER TABLE NODES ADD COLUMN inherited_props BLOB;
--- STMT_UPGRADE_TO_31_FINALIZE
+
 DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST;
 DROP INDEX IF EXISTS I_EXTERNALS_PARENT;
 
@@ -906,25 +700,8 @@ WHERE l.op_depth = 0
 
 /* ------------------------------------------------------------------------- */
 /* Format 32 ....  */
--- STMT_UPGRADE_TO_32
-
-/* Drop old index. ### Remove this part from the upgrade to 31 once bumped */
-DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST;
-DROP INDEX IF EXISTS I_EXTERNALS_PARENT;
-CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath);
-
-DROP INDEX I_NODES_PARENT;
-CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath,
-                                             local_relpath, op_depth);
-
-DROP INDEX I_ACTUAL_PARENT;
-CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
-                                                    local_relpath);
-
-/* ------------------------------------------------------------------------- */
-
-/* Format YYY introduces new handling for conflict information.  */
--- format: YYY
+/* -- STMT_UPGRADE_TO_32
+PRAGMA user_version = 32; */
 
 
 /* ------------------------------------------------------------------------- */

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc-queries.sql?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc-queries.sql Wed Nov  7 12:30:06 2018
@@ -117,6 +117,17 @@ WHERE wc_id = ?1 AND local_relpath = ?2
 ORDER BY op_depth DESC
 LIMIT 1
 
+-- STMT_SELECT_PRESENT_HIGHEST_WORKING_NODES_BY_BASENAME_AND_KIND
+SELECT presence, local_relpath
+FROM nodes n
+WHERE wc_id = ?1 AND local_relpath = RELPATH_JOIN(parent_relpath, ?2)
+  AND kind = ?3
+  AND presence in (MAP_NORMAL, MAP_INCOMPLETE)
+  AND op_depth = (SELECT MAX(op_depth)
+                  FROM NODES w
+                  WHERE w.wc_id = ?1
+                    AND w.local_relpath = n.local_relpath)
+
 -- STMT_SELECT_ACTUAL_NODE
 SELECT changelist, properties, conflict_data
 FROM actual_node
@@ -1293,7 +1304,7 @@ PRAGMA journal_mode = DELETE
 
 -- STMT_FIND_REPOS_PATH_IN_WC
 SELECT local_relpath FROM nodes_current
-  WHERE wc_id = ?1 AND repos_path = ?2 AND revision = ?3
+  WHERE wc_id = ?1 AND repos_path = ?2
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc.h Wed Nov  7 12:30:06 2018
@@ -159,6 +159,7 @@ extern "C" {
  *
  * == 1.8.x shipped with format 31
  * == 1.9.x shipped with format 31
+ * == 1.10.x shipped with format 31
  *
  * Please document any further format changes here.
  */
@@ -288,6 +289,7 @@ struct svn_wc_traversal_info_t
 #define SVN_WC__ADM_TMP                 "tmp"
 #define SVN_WC__ADM_PRISTINE            "pristine"
 #define SVN_WC__ADM_NONEXISTENT_PATH    "nonexistent-path"
+#define SVN_WC__ADM_EXPERIMENTAL        "experimental"
 
 /* The basename of the ".prej" file, if a directory ever has property
    conflicts.  This .prej file will appear *within* the conflicted
@@ -480,7 +482,7 @@ svn_wc__conflicted_for_update_p(svn_bool
 
 /* Internal version of svn_wc_transmit_text_deltas3(). */
 svn_error_t *
-svn_wc__internal_transmit_text_deltas(const char **tempfile,
+svn_wc__internal_transmit_text_deltas(svn_stream_t *tempstream,
                                       const svn_checksum_t **new_text_base_md5_checksum,
                                       const svn_checksum_t **new_text_base_sha1_checksum,
                                       svn_wc__db_t *db,

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc_db.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc_db.c Wed Nov  7 12:30:06 2018
@@ -1371,9 +1371,6 @@ init_db(/* output values */
 
   /* Create the database's schema.  */
   SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_SCHEMA));
-  SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_NODES));
-  SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_NODES_TRIGGERS));
-  SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_EXTERNALS));
 
   SVN_ERR(svn_wc__db_install_schema_statistics(db, scratch_pool));
 
@@ -6842,7 +6839,7 @@ revert_maybe_raise_moved_away(svn_wc__db
     }
 
   SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action,
-                                              NULL,
+                                              NULL, NULL,
                                               db, wcroot->abspath,
                                               conflict,
                                               scratch_pool,
@@ -16528,8 +16525,8 @@ db_process_commit_queue(svn_wc__db_t *db
                                                         iterpool),
                                                     iterpool, iterpool));
 
-              lock_remove_txn(queue->wcroot, cqi->local_relpath, work_item,
-                              iterpool);
+              SVN_ERR(lock_remove_txn(queue->wcroot, cqi->local_relpath,
+                                      work_item, iterpool));
             }
           if (cqi->remove_changelist)
             SVN_ERR(svn_wc__db_op_set_changelist(db,
@@ -16581,13 +16578,12 @@ svn_wc__db_process_commit_queue(svn_wc__
 }
 
 svn_error_t *
-svn_wc__find_repos_node_in_wc(apr_array_header_t **local_abspath_list,
-                              svn_wc__db_t *db,
-                              const char *wri_abspath,
-                              const char *repos_relpath,
-                              svn_revnum_t rev,
-                              apr_pool_t *result_pool,
-                              apr_pool_t *scratch_pool)
+svn_wc__db_find_repos_node_in_wc(apr_array_header_t **local_abspath_list,
+                                 svn_wc__db_t *db,
+                                 const char *wri_abspath,
+                                 const char *repos_relpath,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool)
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *wri_relpath;
@@ -16603,7 +16599,7 @@ svn_wc__find_repos_node_in_wc(apr_array_
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_FIND_REPOS_PATH_IN_WC));
-  SVN_ERR(svn_sqlite__bindf(stmt, "isr", wcroot->wc_id, repos_relpath, rev));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, repos_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
   *local_abspath_list = apr_array_make(result_pool, have_row ? 1 : 0,
@@ -16624,3 +16620,46 @@ svn_wc__find_repos_node_in_wc(apr_array_
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
+svn_error_t *
+svn_wc__db_find_working_nodes_with_basename(apr_array_header_t **local_abspaths,
+                                            svn_wc__db_t *db,
+                                            const char *wri_abspath,
+                                            const char *basename,
+                                            svn_node_kind_t kind,
+                                            apr_pool_t *result_pool,
+                                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *wri_relpath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &wri_relpath, db,
+                                                wri_abspath, scratch_pool,
+                                                scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+            STMT_SELECT_PRESENT_HIGHEST_WORKING_NODES_BY_BASENAME_AND_KIND));
+  SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, basename,
+                            kind_map, kind));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  *local_abspaths = apr_array_make(result_pool, 1, sizeof(const char *));
+
+  while (have_row)
+    {
+      const char *local_relpath;
+      const char *local_abspath;
+
+      local_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+      local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
+                                      result_pool);
+      APR_ARRAY_PUSH(*local_abspaths, const char *) = local_abspath;
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  return svn_error_trace(svn_sqlite__reset(stmt));
+}

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc_db.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc_db.h Wed Nov  7 12:30:06 2018
@@ -3420,6 +3420,17 @@ svn_wc__db_update_incoming_move(svn_wc__
                                 void *notify_baton,
                                 apr_pool_t *scratch_pool);
 
+/* Merge locally added dir tree conflict victim at LOCAL_ABSPATH with the
+ * directory since added to the BASE layer by an update operation. */
+svn_error_t *
+svn_wc__db_update_local_add(svn_wc__db_t *db,
+                            const char *local_abspath,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
+                            svn_wc_notify_func2_t notify_func,
+                            void *notify_baton,
+                            apr_pool_t *scratch_pool);
+
 /* LOCAL_ABSPATH is moved to MOVE_DST_ABSPATH.  MOVE_SRC_ROOT_ABSPATH
  * is the root of the move to MOVE_DST_OP_ROOT_ABSPATH.
  * DELETE_ABSPATH is the op-root of the move; it's the same
@@ -3478,21 +3489,37 @@ svn_wc__required_lock_for_resolve(const
 
 /* Return an array of const char * elements, which represent local absolute
  * paths for nodes, within the working copy indicated by WRI_ABSPATH, which
- * correspond to REPOS_RELPATH@REV.
- * If no such nodes exist, return an empty array.
+ * correspond to REPOS_RELPATH. If no such nodes exist, return an empty array.
  *
  * Note that this function returns each and every such node that is known
  * in the WC, including, for example, nodes that were children of a directory
  * which has been replaced.
  */
 svn_error_t *
-svn_wc__find_repos_node_in_wc(apr_array_header_t **local_abspath_list,
-                              svn_wc__db_t *db,
-                              const char *wri_abspath,
-                              const char *repos_relpath,
-                              svn_revnum_t rev,
-                              apr_pool_t *result_pool,
-                              apr_pool_t *scratch_pool);
+svn_wc__db_find_repos_node_in_wc(apr_array_header_t **local_abspath_list,
+                                 svn_wc__db_t *db,
+                                 const char *wri_abspath,
+                                 const char *repos_relpath,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool);
+
+/* Return an array of const char * elements, which represent local absolute
+ * paths for nodes, within the working copy indicated by WRI_ABSPATH, which
+ * have a basename matching BASENAME and have node kind KIND.
+ * If no such nodes exist, return an empty array.
+ *
+ * This function returns only paths to nodes which are present in the highest
+ * layer of the WC. In other words, paths to deleted and/or excluded nodes are
+ * never returned.
+ */
+svn_error_t *
+svn_wc__db_find_working_nodes_with_basename(apr_array_header_t **local_abspaths,
+                                            svn_wc__db_t *db,
+                                            const char *wri_abspath,
+                                            const char *basename,
+                                            svn_node_kind_t kind,
+                                            apr_pool_t *result_pool,
+                                            apr_pool_t *scratch_pool);
 /* @} */
 
 typedef svn_error_t * (*svn_wc__db_verify_cb_t)(void *baton,

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc_db_update_move.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc_db_update_move.c Wed Nov  7 12:30:06 2018
@@ -21,13 +21,14 @@
  * ====================================================================
  */
 
-/* This implements editors and an edit drivers which are used to resolve
- * "incoming edit, local move-away" and "incoming move, local edit" tree
- * conflict resulting from an update (or switch).
- *
- * Our goal is to be able to resolve this conflict such that the end
- * result is just the same as if the user had run the update *before*
- * the local (or incoming) move.
+/* This implements editors and edit drivers which are used to resolve
+ * "incoming edit, local move-away", "incoming move, local edit", and
+ * "incoming add, local add" tree conflicts resulting from an update
+ * (or switch).
+ *
+ * Our goal is to be able to resolve conflicts such that the end result
+ * is just the same as if the user had run the update *before* the local
+ * (or incoming) move or local add.
  *
  * -- Updating local moves --
  *
@@ -102,6 +103,30 @@
  * to working files/directories in the move destination, and there should be
  * tree-conflicts in the move destination where it was not possible to
  * update the working files/directories.
+ *
+ * -- Updating local adds --
+ *
+ * When an update (or switch) adds a directory tree it creates corresponding
+ * nodes in the BASE tree. Any existing locally added nodes are bumped to a
+ * higher layer with the top-most locally added directory as op-root.
+ * In-between, the update inserts a base-deleted layer, i.e. it schedules the
+ * directory in the BASE tree for removal upon the next commit, to be replaced
+ * by the locally added directory.
+ *
+ * The driver sees two NODES trees: The BASE layer, and the WORKING layer
+ * which represents the locally added tree.
+ * The driver will compare the two NODES trees and drive an editor to
+ * merge WORKING tree nodes with the nodes in the BASE tree.
+ *
+ * The whole drive occurs as one single wc.db transaction.
+ * Directories which exist in both trees become part of the BASE tree, with
+ * properties merged.
+ * Files which exist in both trees are merged (there is no common ancestor,
+ * so the common ancestor in this merge is the empty file).
+ * Files and directories which exist only in the WORKING layer become
+ * local-add op-roots of their own.
+ * Mismatching node kinds produce new 'incoming add vs local add upon update'
+ * tree conflicts which must be resolved individually later on.
  */
 
 #define SVN_WC__I_AM_WC_DB
@@ -386,8 +411,13 @@ create_tree_conflict(svn_skel_t **confli
     ? svn_dirent_join(wcroot->abspath,
                       move_src_op_root_relpath, scratch_pool)
     : NULL;
+  const char *move_dst_op_root_abspath
+    = dst_op_root_relpath
+    ? svn_dirent_join(wcroot->abspath,
+                      dst_op_root_relpath, scratch_pool)
+    : NULL;
   const char *old_repos_relpath_part
-    = old_repos_relpath
+    = old_repos_relpath && old_version
     ? svn_relpath_skip_ancestor(old_version->path_in_repos,
                                 old_repos_relpath)
     : NULL;
@@ -443,7 +473,7 @@ create_tree_conflict(svn_skel_t **confli
 
           SVN_ERR(svn_wc__conflict_read_tree_conflict(&existing_reason,
                                                       &existing_action,
-                                                      &existing_abspath,
+                                                      &existing_abspath, NULL,
                                                       db, wcroot->abspath,
                                                       conflict,
                                                       scratch_pool,
@@ -475,13 +505,18 @@ create_tree_conflict(svn_skel_t **confli
                      reason,
                      action,
                      move_src_op_root_abspath,
+                     move_dst_op_root_abspath,
                      result_pool,
                      scratch_pool));
 
-  conflict_old_version = svn_wc_conflict_version_create2(
-                               old_version->repos_url, old_version->repos_uuid,
-                               old_repos_relpath, old_version->peg_rev,
-                               old_kind, scratch_pool);
+  if (old_version)
+    conflict_old_version = svn_wc_conflict_version_create2(
+                                 old_version->repos_url,
+                                 old_version->repos_uuid,
+                                 old_repos_relpath, old_version->peg_rev,
+                                 old_kind, scratch_pool);
+  else
+    conflict_old_version = NULL;
 
   conflict_new_version = svn_wc_conflict_version_create2(
                            new_version->repos_url, new_version->repos_uuid,
@@ -2813,6 +2848,774 @@ svn_wc__db_update_incoming_move(svn_wc__
   return SVN_NO_ERROR;
 }
 
+typedef struct update_local_add_baton_t {
+  int add_op_depth;
+  svn_wc__db_t *db;
+  svn_wc__db_wcroot_t *wcroot;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+
+  /* We refer to these if raising new tree conflicts. */
+  const svn_wc_conflict_version_t *new_version;
+} update_local_add_baton_t;
+
+typedef struct added_node_baton_t {
+  struct update_local_add_baton_t *b;
+  struct added_node_baton_t *pb;
+  const char *local_relpath;
+  svn_boolean_t skip;
+  svn_boolean_t edited;
+} added_node_baton_t;
+
+
+static svn_error_t *
+update_local_add_mark_node_edited(added_node_baton_t *nb,
+                                  apr_pool_t *scratch_pool)
+{
+  if (nb->edited)
+    return SVN_NO_ERROR;
+
+  if (nb->pb)
+    {
+      SVN_ERR(update_local_add_mark_node_edited(nb->pb, scratch_pool));
+
+      if (nb->pb->skip)
+        nb->skip = TRUE;
+    }
+
+  nb->edited = TRUE;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_local_add_mark_parent_edited(added_node_baton_t *nb,
+                                    apr_pool_t *scratch_pool)
+{
+  SVN_ERR_ASSERT(nb && nb->pb);
+
+  SVN_ERR(update_local_add_mark_node_edited(nb->pb, scratch_pool));
+
+  if (nb->pb->skip)
+    nb->skip = TRUE;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+mark_update_add_add_tree_conflict(added_node_baton_t *nb,
+                                  svn_node_kind_t base_kind,
+                                  svn_node_kind_t working_kind,
+                                  svn_wc_conflict_reason_t local_change,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
+
+{
+  svn_wc__db_t *db = nb->b->db;
+  svn_wc__db_wcroot_t *wcroot = nb->b->wcroot;
+  svn_wc_conflict_version_t *new_version;
+  svn_skel_t *conflict;
+
+  new_version = svn_wc_conflict_version_dup(nb->b->new_version, result_pool);
+
+  /* Fill in conflict info templates with info for this node. */
+  SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, &new_version->peg_rev,
+                                            &new_version->path_in_repos,
+                                            NULL, NULL, NULL, NULL, NULL, NULL,
+                                            NULL, NULL, NULL, NULL, NULL,
+                                            wcroot, nb->local_relpath,
+                                            scratch_pool, scratch_pool));
+  new_version->node_kind = base_kind;
+
+  SVN_ERR(create_tree_conflict(&conflict, wcroot, nb->local_relpath,
+                               nb->local_relpath, db, NULL, new_version,
+                               svn_wc_operation_update,
+                               svn_node_none, base_kind, NULL,
+                               local_change, svn_wc_conflict_action_add,
+                               NULL, scratch_pool, scratch_pool));
+
+  SVN_ERR(update_move_list_add(wcroot, nb->local_relpath, db,
+                               svn_wc_notify_tree_conflict, working_kind,
+                               svn_wc_notify_state_inapplicable,
+                               svn_wc_notify_state_inapplicable,
+                               conflict, NULL, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_local_add_notify_obstructed_or_missing(added_node_baton_t *nb,
+                                              svn_node_kind_t working_kind,
+                                              svn_node_kind_t kind_on_disk,
+                                              apr_pool_t *scratch_pool)
+{
+  svn_wc_notify_state_t content_state;
+
+  if (kind_on_disk == svn_node_none)
+      content_state = svn_wc_notify_state_missing;
+  else
+      content_state = svn_wc_notify_state_obstructed;
+
+  SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, nb->b->db,
+                               svn_wc_notify_skip, working_kind,
+                               content_state, svn_wc_notify_state_inapplicable,
+                               NULL, NULL, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_update_add_new_file(added_node_baton_t *nb,
+                              svn_node_kind_t base_kind,
+                              const svn_checksum_t *base_checksum,
+                              apr_hash_t *base_props,
+                              svn_node_kind_t working_kind,
+                              const svn_checksum_t *working_checksum,
+                              apr_hash_t *working_props,
+                              apr_pool_t *scratch_pool)
+{
+  const char *local_abspath;
+  svn_node_kind_t kind_on_disk;
+
+  SVN_ERR(update_local_add_mark_parent_edited(nb, scratch_pool));
+  if (nb->skip)
+    return SVN_NO_ERROR;
+
+  if (base_kind != svn_node_none)
+    {
+      SVN_ERR(mark_update_add_add_tree_conflict(nb, base_kind, svn_node_file,
+                                                svn_wc_conflict_reason_added,
+                                                scratch_pool, scratch_pool));
+      nb->skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+  
+  /* Check for obstructions. */
+  local_abspath = svn_dirent_join(nb->b->wcroot->abspath, nb->local_relpath,
+                                  scratch_pool);
+  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+  if (kind_on_disk != svn_node_file)
+    {
+      SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, working_kind,
+                                                            kind_on_disk,
+                                                            scratch_pool));
+      nb->skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  /* Nothing else to do. Locally added files are an op-root in NODES. */
+
+  SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, nb->b->db,
+                               svn_wc_notify_update_add, svn_node_file,
+                               svn_wc_notify_state_inapplicable,
+                               svn_wc_notify_state_inapplicable,
+                               NULL, NULL, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_update_add_new_directory(added_node_baton_t *nb,
+                                   svn_node_kind_t base_kind,
+                                   apr_hash_t *base_props,
+                                   apr_hash_t *working_props,
+                                   apr_pool_t *scratch_pool)
+{
+  const char *local_abspath;
+  svn_node_kind_t kind_on_disk;
+
+  SVN_ERR(update_local_add_mark_parent_edited(nb, scratch_pool));
+  if (nb->skip)
+    return SVN_NO_ERROR;
+
+  if (base_kind != svn_node_none)
+    {
+      SVN_ERR(mark_update_add_add_tree_conflict(nb, base_kind, svn_node_dir,
+                                                svn_wc_conflict_reason_added,
+                                                scratch_pool, scratch_pool));
+      nb->skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  /* Check for obstructions. */
+  local_abspath = svn_dirent_join(nb->b->wcroot->abspath, nb->local_relpath,
+                                  scratch_pool);
+  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+  if (kind_on_disk != svn_node_dir)
+    {
+      SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, svn_node_dir,
+                                                            kind_on_disk,
+                                                            scratch_pool));
+      nb->skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  /* Nothing else to do. Locally added directories are an op-root in NODES. */
+
+  SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, nb->b->db,
+                               svn_wc_notify_update_add, svn_node_dir,
+                               svn_wc_notify_state_inapplicable,
+                               svn_wc_notify_state_inapplicable,
+                               NULL, NULL, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_incoming_add_merge_props(svn_wc_notify_state_t *prop_state,
+                                svn_skel_t **conflict_skel,
+                                const char *local_relpath,
+                                apr_hash_t *base_props,
+                                apr_hash_t *working_props,
+                                svn_wc__db_t *db,
+                                svn_wc__db_wcroot_t *wcroot,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool)
+{
+  apr_hash_t *new_actual_props;
+  apr_array_header_t *propchanges;
+  const char *local_abspath = svn_dirent_join(wcroot->abspath,
+                                              local_relpath,
+                                              scratch_pool);
+
+  /*
+   * Run a 3-way prop merge to update the props, using the empty props
+   * as the merge base, the post-update props as the merge-left version, and
+   * the current props of the added working file as the merge-right version.
+   */
+  SVN_ERR(svn_prop_diffs(&propchanges, working_props,
+                         apr_hash_make(scratch_pool), scratch_pool));
+  SVN_ERR(svn_wc__merge_props(conflict_skel, prop_state, &new_actual_props,
+                              db, local_abspath,
+                              apr_hash_make(scratch_pool),
+                              base_props, working_props, propchanges,
+                              result_pool, scratch_pool));
+
+  /* Install the new actual props. */
+  if (apr_hash_count(new_actual_props) > 0)
+    SVN_ERR(svn_wc__db_op_set_props_internal(wcroot, local_relpath,
+                                             new_actual_props,
+                                             svn_wc__has_magic_property(
+                                                      propchanges),
+                                             scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_update_add_merge_files(added_node_baton_t *nb,
+                                 const svn_checksum_t *working_checksum,
+                                 const svn_checksum_t *base_checksum,
+                                 apr_hash_t *working_props,
+                                 apr_hash_t *base_props,
+                                 apr_pool_t *scratch_pool)
+{
+  update_local_add_baton_t *b = nb->b;
+  apr_array_header_t *propchanges;
+  svn_boolean_t is_modified;
+  enum svn_wc_merge_outcome_t merge_outcome;
+  svn_skel_t *conflict_skel = NULL;
+  svn_wc_notify_state_t prop_state, content_state;
+  svn_skel_t *work_items = NULL;
+  svn_node_kind_t kind_on_disk;
+  const char *local_abspath = svn_dirent_join(b->wcroot->abspath,
+                                              nb->local_relpath,
+                                              scratch_pool);
+
+  SVN_ERR(update_local_add_mark_node_edited(nb, scratch_pool));
+  if (nb->skip)
+    return SVN_NO_ERROR;
+
+  /* Check for on-disk obstructions or missing files. */
+  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+  if (kind_on_disk != svn_node_file)
+    {
+      SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, svn_node_file,
+                                                            kind_on_disk,
+                                                            scratch_pool));
+      nb->skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(update_incoming_add_merge_props(&prop_state, &conflict_skel,
+                                          nb->local_relpath,
+                                          base_props, working_props,
+                                          b->db, b->wcroot,
+                                          scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_wc__internal_file_modified_p(&is_modified,
+                                           b->db, local_abspath,
+                                           FALSE /* exact_comparison */,
+                                           scratch_pool));
+  if (!is_modified)
+    {
+      svn_skel_t *work_item = NULL;
+
+      SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db,
+                                            local_abspath, NULL,
+                                            /* FIXME: use_commit_times? */
+                                            FALSE,
+                                            TRUE,  /* record_file_info */
+                                            scratch_pool, scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+      content_state = svn_wc_notify_state_changed;
+    }
+  else
+    {
+      const char *empty_file_abspath;
+      const char *pristine_abspath;
+      svn_skel_t *work_item = NULL;
+
+      /*
+       * Run a 3-way merge to update the file, using the empty file
+       * merge base, the post-update pristine text as the merge-left version,
+       * and the locally added content of the working file as the merge-right
+       * version.
+       */
+      SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file_abspath, NULL,
+                                       svn_io_file_del_on_pool_cleanup,
+                                       scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_pristine_get_path(&pristine_abspath, b->db,
+                                           b->wcroot->abspath, base_checksum,
+                                           scratch_pool, scratch_pool));
+
+      /* Create a property diff which shows all props as added. */
+      SVN_ERR(svn_prop_diffs(&propchanges, working_props,
+                             apr_hash_make(scratch_pool), scratch_pool));
+
+      SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
+                                     &merge_outcome, b->db,
+                                     empty_file_abspath,
+                                     pristine_abspath,
+                                     local_abspath,
+                                     local_abspath,
+                                     NULL, NULL, NULL, /* diff labels */
+                                     apr_hash_make(scratch_pool),
+                                     FALSE, /* dry-run */
+                                     NULL, /* diff3-cmd */
+                                     NULL, /* merge options */
+                                     propchanges,
+                                     b->cancel_func, b->cancel_baton,
+                                     scratch_pool, scratch_pool));
+
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+      if (merge_outcome == svn_wc_merge_conflict)
+        content_state = svn_wc_notify_state_conflicted;
+      else
+        content_state = svn_wc_notify_state_merged;
+    }
+
+  /* If there are any conflicts to be stored, convert them into work items
+   * too. */
+  if (conflict_skel)
+    {
+      svn_wc_conflict_version_t *new_version;
+      svn_node_kind_t new_kind;
+      svn_revnum_t new_rev;
+      const char *repos_relpath;
+
+      new_version = svn_wc_conflict_version_dup(nb->b->new_version,
+                                                scratch_pool);
+      SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev,
+                                                &repos_relpath, NULL, NULL,
+                                                NULL, NULL, NULL, NULL, NULL,
+                                                NULL, NULL, NULL, NULL,
+                                                b->wcroot, nb->local_relpath,
+                                                scratch_pool, scratch_pool));
+      /* Fill in conflict info templates with info for this node. */
+      new_version->path_in_repos = repos_relpath;
+      new_version->node_kind = new_kind;
+      new_version->peg_rev = new_rev;
+
+      /* Create conflict markers. */
+      SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel, NULL,
+                                                  new_version, scratch_pool,
+                                                  scratch_pool));
+      if (prop_state == svn_wc_notify_state_conflicted)
+        SVN_ERR(svn_wc__conflict_create_markers(&work_items, b->db,
+                                                local_abspath,
+                                                conflict_skel,
+                                                scratch_pool,
+                                                scratch_pool));
+    }
+
+  SVN_ERR(update_move_list_add(b->wcroot, nb->local_relpath, b->db,
+                               svn_wc_notify_update_update,
+                               svn_node_file, content_state, prop_state,
+                               conflict_skel, work_items, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_update_add_merge_dirprops(added_node_baton_t *nb,
+                                    apr_hash_t *working_props,
+                                    apr_hash_t *base_props,
+                                    apr_pool_t *scratch_pool)
+{
+  update_local_add_baton_t *b = nb->b;
+  svn_skel_t *conflict_skel = NULL;
+  svn_wc_notify_state_t prop_state;
+  svn_skel_t *work_items = NULL;
+  svn_node_kind_t kind_on_disk;
+  const char *local_abspath = svn_dirent_join(b->wcroot->abspath,
+                                              nb->local_relpath,
+                                              scratch_pool);
+
+  SVN_ERR(update_local_add_mark_node_edited(nb, scratch_pool));
+  if (nb->skip)
+    return SVN_NO_ERROR;
+
+  /* Check for on-disk obstructions or missing files. */
+  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+  if (kind_on_disk != svn_node_dir)
+    {
+      SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, svn_node_dir,
+                                                            kind_on_disk,
+                                                            scratch_pool));
+      nb->skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(update_incoming_add_merge_props(&prop_state, &conflict_skel,
+                                          nb->local_relpath,
+                                          base_props, working_props,
+                                          b->db, b->wcroot,
+                                          scratch_pool, scratch_pool));
+
+  /* If there are any conflicts to be stored, convert them into work items. */
+  if (conflict_skel && prop_state == svn_wc_notify_state_conflicted)
+    {
+      svn_wc_conflict_version_t *new_version;
+      svn_node_kind_t new_kind;
+      svn_revnum_t new_rev;
+      const char *repos_relpath;
+
+      new_version = svn_wc_conflict_version_dup(nb->b->new_version,
+                                                scratch_pool);
+      SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev,
+                                                &repos_relpath, NULL, NULL,
+                                                NULL, NULL, NULL, NULL, NULL,
+                                                NULL, NULL, NULL, NULL,
+                                                b->wcroot, nb->local_relpath,
+                                                scratch_pool, scratch_pool));
+      /* Fill in conflict info templates with info for this node. */
+      new_version->path_in_repos = repos_relpath;
+      new_version->node_kind = new_kind;
+      new_version->peg_rev = new_rev;
+
+      /* Create conflict markers. */
+      SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel, NULL,
+                                                  new_version, scratch_pool,
+                                                  scratch_pool));
+      SVN_ERR(svn_wc__conflict_create_markers(&work_items, b->db,
+                                              local_abspath,
+                                              conflict_skel,
+                                              scratch_pool,
+                                              scratch_pool));
+    }
+
+  SVN_ERR(update_move_list_add(b->wcroot, nb->local_relpath, b->db,
+                               svn_wc_notify_update_update, svn_node_dir,
+                               svn_wc_notify_state_inapplicable, prop_state,
+                               conflict_skel, work_items, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_locally_added_node(added_node_baton_t *nb,
+                          apr_pool_t *scratch_pool)
+{
+  update_local_add_baton_t *b = nb->b;
+  svn_wc__db_wcroot_t *wcroot = b->wcroot;
+  svn_wc__db_t *db = b->db;
+  svn_node_kind_t base_kind, working_kind;
+  const svn_checksum_t *base_checksum;
+  apr_hash_t *base_props, *working_props;
+  apr_array_header_t *base_children, *working_children;
+  const char *local_abspath = svn_dirent_join(wcroot->abspath,
+                                              nb->local_relpath,
+                                              scratch_pool);
+
+  if (b->cancel_func)
+    SVN_ERR(b->cancel_func(b->cancel_baton));
+
+  if (nb->skip)
+    return SVN_NO_ERROR;
+
+  /* Compare the tree conflict victim's BASE layer to the working layer. */
+  SVN_ERR(get_info(&base_props, &base_checksum, &base_children, &base_kind,
+                   nb->local_relpath, 0, wcroot, scratch_pool, scratch_pool));
+  SVN_ERR(get_working_info(&working_props, NULL, &working_children,
+                           &working_kind, nb->local_relpath, wcroot,
+                           scratch_pool, scratch_pool));
+  if (working_kind == svn_node_none)
+    {
+      svn_node_kind_t kind_on_disk;
+      svn_skel_t *work_item = NULL;
+
+      /* Skip obstructed nodes. */
+      SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk,
+                                scratch_pool));
+      if (kind_on_disk != base_kind && kind_on_disk != svn_node_none)
+        {
+          SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath,
+                                       nb->b->db,
+                                       svn_wc_notify_skip,
+                                       base_kind,
+                                       svn_wc_notify_state_obstructed,
+                                       svn_wc_notify_state_inapplicable,
+                                       NULL, NULL, scratch_pool));
+          nb->skip = TRUE;
+          return SVN_NO_ERROR;
+        }
+
+      /* The working tree has no node here. The working copy of this node
+       * is currently not installed because the base tree is shadowed.
+       * Queue an installation of this node into the working copy. */
+      if (base_kind == svn_node_file || base_kind == svn_node_symlink)
+        SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath,
+                                              NULL,
+                                              /* FIXME: use_commit_times? */
+                                              FALSE,
+                                              TRUE,  /* record_file_info */
+                                              scratch_pool, scratch_pool));
+      else if (base_kind == svn_node_dir)
+        SVN_ERR(svn_wc__wq_build_dir_install(&work_item, db, local_abspath,
+                                             scratch_pool, scratch_pool));
+
+      if (work_item)
+        SVN_ERR(update_move_list_add(wcroot, nb->local_relpath, db,
+                                     svn_wc_notify_update_add,
+                                     base_kind,
+                                     svn_wc_notify_state_inapplicable,
+                                     svn_wc_notify_state_inapplicable,
+                                     NULL, work_item, scratch_pool));
+      return SVN_NO_ERROR;
+    }
+
+  if (base_kind != working_kind)
+    {
+      if (working_kind == svn_node_file || working_kind == svn_node_symlink)
+        {
+          svn_checksum_t *working_checksum = NULL;
+
+          if (base_checksum)
+            SVN_ERR(svn_io_file_checksum2(&working_checksum, local_abspath,
+                                          base_checksum->kind, scratch_pool));
+          SVN_ERR(tc_editor_update_add_new_file(nb, base_kind, base_checksum,
+                                                base_props, working_kind,
+                                                working_checksum, working_props,
+                                                scratch_pool));
+        }
+      else if (working_kind == svn_node_dir)
+        SVN_ERR(tc_editor_update_add_new_directory(nb, base_kind, base_props,
+                                                   working_props,
+                                                   scratch_pool));
+    }
+  else
+    {
+      svn_boolean_t props_equal;
+
+      SVN_ERR(props_match(&props_equal, base_props, working_props,
+                          scratch_pool));
+
+      if (working_kind == svn_node_file || working_kind == svn_node_symlink)
+        {
+          svn_checksum_t *working_checksum;
+
+          SVN_ERR_ASSERT(base_checksum);
+          SVN_ERR(svn_io_file_checksum2(&working_checksum, local_abspath,
+                                        base_checksum->kind, scratch_pool));
+          if (!props_equal || !svn_checksum_match(base_checksum,
+                                                  working_checksum))
+            SVN_ERR(tc_editor_update_add_merge_files(nb, working_checksum,
+                                                     base_checksum,
+                                                     working_props, base_props,
+                                                     scratch_pool));
+        }
+      else if (working_kind == svn_node_dir && !props_equal)
+        SVN_ERR(tc_editor_update_add_merge_dirprops(nb, working_props,
+                                                    base_props,
+                                                    scratch_pool));
+    }
+
+  if (nb->skip)
+    return SVN_NO_ERROR;
+
+  if (working_kind == svn_node_dir)
+    {
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+      int i = 0, j = 0;
+
+      while (i < base_children->nelts || j < working_children->nelts)
+        {
+          const char *child_name;
+          svn_boolean_t base_only = FALSE, working_only = FALSE;
+          added_node_baton_t cnb = { 0 };
+
+          cnb.pb = nb;
+          cnb.b = nb->b;
+          cnb.skip = FALSE;
+
+          svn_pool_clear(iterpool);
+          if (i >= base_children->nelts)
+            {
+              working_only = TRUE;
+              child_name = APR_ARRAY_IDX(working_children, j, const char *);
+            }
+          else if (j >= working_children->nelts)
+            {
+              base_only = TRUE;
+              child_name = APR_ARRAY_IDX(base_children, i, const char *);
+            }
+          else
+            {
+              const char *base_name = APR_ARRAY_IDX(base_children, i,
+                                                    const char *);
+              const char *working_name = APR_ARRAY_IDX(working_children, j,
+                                                       const char *);
+              int cmp = strcmp(base_name, working_name);
+
+              if (cmp > 0)
+                working_only = TRUE;
+              else if (cmp < 0)
+                base_only = TRUE;
+
+              child_name = working_only ? working_name : base_name;
+            }
+
+          cnb.local_relpath = svn_relpath_join(nb->local_relpath, child_name,
+                                               iterpool);
+
+          SVN_ERR(update_locally_added_node(&cnb, iterpool));
+
+          if (!working_only)
+            ++i;
+          if (!base_only)
+            ++j;
+
+          if (nb->skip) /* Does parent now want a skip? */
+            break;
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* The body of svn_wc__db_update_local_add(). */
+static svn_error_t *
+update_local_add(svn_revnum_t *new_rev,
+                svn_wc__db_t *db,
+                svn_wc__db_wcroot_t *wcroot,
+                const char *local_relpath,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
+                apr_pool_t *scratch_pool)
+{
+  update_local_add_baton_t b = { 0 };
+  added_node_baton_t nb = { 0 };
+  const char *repos_root_url;
+  const char *repos_uuid;
+  const char *repos_relpath;
+  apr_int64_t repos_id;
+  svn_node_kind_t new_kind;
+  svn_sqlite__stmt_t *stmt;
+
+  b.add_op_depth = relpath_depth(local_relpath); /* DST op-root */
+
+  SVN_ERR(verify_write_lock(wcroot, local_relpath, scratch_pool));
+
+  b.db = db;
+  b.wcroot = wcroot;
+  b.cancel_func = cancel_func;
+  b.cancel_baton = cancel_baton;
+
+  /* Read new version info from the updated BASE node. */
+  SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, new_rev,
+                                            &repos_relpath, &repos_id,
+                                            NULL, NULL, NULL, NULL, NULL,
+                                            NULL, NULL, NULL, NULL, NULL,
+                                            wcroot, local_relpath,
+                                            scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, wcroot,
+                                      repos_id, scratch_pool));
+  b.new_version = svn_wc_conflict_version_create2(repos_root_url, repos_uuid,
+                                                  repos_relpath, *new_rev,
+                                                  new_kind, scratch_pool);
+
+  /* Create a new, and empty, list for notification information. */
+  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+                                      STMT_CREATE_UPDATE_MOVE_LIST));
+
+  /* Drive the editor... */
+  nb.b = &b;
+  nb.local_relpath = local_relpath;
+  nb.skip = FALSE;
+  SVN_ERR(update_locally_added_node(&nb, scratch_pool));
+
+  /* The conflict victim is now part of the base tree.
+   * Remove the locally added version of the conflict victim and its children.
+   * Any children we want to retain are at a higher op-depth so they won't
+   * be deleted by this statement. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_DELETE_WORKING_OP_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
+                            relpath_depth(local_relpath)));
+  SVN_ERR(svn_sqlite__update(NULL, stmt));
+
+  /* Remove the tree conflict marker. */
+  SVN_ERR(svn_wc__db_op_mark_resolved_internal(wcroot, local_relpath, db,
+                                               FALSE, FALSE, TRUE,
+                                               NULL, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_update_local_add(svn_wc__db_t *db,
+                            const char *local_abspath,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
+                            svn_wc_notify_func2_t notify_func,
+                            void *notify_baton,
+                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  svn_revnum_t new_rev;
+  const char *local_relpath;
+
+  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(update_local_add(&new_rev, db, wcroot,
+                                       local_relpath, 
+                                       cancel_func, cancel_baton,
+                                       scratch_pool),
+                      wcroot);
+
+  /* Send all queued up notifications. */
+  SVN_ERR(svn_wc__db_update_move_list_notify(wcroot, new_rev, new_rev,
+                                             notify_func, notify_baton,
+                                             scratch_pool));
+  if (notify_func)
+    {
+      svn_wc_notify_t *notify;
+
+      notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
+                                                    local_relpath,
+                                                    scratch_pool),
+                                    svn_wc_notify_update_completed,
+                                    scratch_pool);
+      notify->kind = svn_node_none;
+      notify->content_state = svn_wc_notify_state_inapplicable;
+      notify->prop_state = svn_wc_notify_state_inapplicable;
+      notify->revision = new_rev;
+      notify_func(notify_baton, notify, scratch_pool);
+    }
+
+
+  return SVN_NO_ERROR;
+}
 /* Set *CAN_BUMP to TRUE if DEPTH is sufficient to cover the entire
    tree  LOCAL_RELPATH at OP_DEPTH, to FALSE otherwise. */
 static svn_error_t *
@@ -3302,7 +4105,7 @@ fetch_conflict_details(int *src_op_depth
 
   SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason,
                                               action,
-                                              &move_src_op_root_abspath,
+                                              &move_src_op_root_abspath, NULL,
                                               db, local_abspath,
                                               conflict_skel, result_pool,
                                               scratch_pool));

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wc_db_wcroot.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wc_db_wcroot.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wc_db_wcroot.c Wed Nov  7 12:30:06 2018
@@ -528,6 +528,7 @@ svn_wc__db_wcroot_parse_local_abspath(sv
   const char *adm_relpath;
   /* Non-NULL if WCROOT is found through a symlink: */
   const char *symlink_wcroot_abspath = NULL;
+  apr_pool_t *iterpool;
 
   /* ### we need more logic for finding the database (if it is located
      ### outside of the wcroot) and then managing all of that within DB.
@@ -613,16 +614,20 @@ svn_wc__db_wcroot_parse_local_abspath(sv
      database in the right place. If we find it... great! If not, then
      peel off some components, and try again. */
 
+  iterpool = svn_pool_create(scratch_pool);
   adm_relpath = svn_wc_get_adm_dir(scratch_pool);
   while (TRUE)
     {
       svn_error_t *err;
       svn_node_kind_t adm_subdir_kind;
 
-      const char *adm_subdir = svn_dirent_join(local_abspath, adm_relpath,
-                                               scratch_pool);
+      const char *adm_subdir;
 
-      SVN_ERR(svn_io_check_path(adm_subdir, &adm_subdir_kind, scratch_pool));
+      svn_pool_clear(iterpool);
+
+      adm_subdir = svn_dirent_join(local_abspath, adm_relpath, iterpool);
+
+      SVN_ERR(svn_io_check_path(adm_subdir, &adm_subdir_kind, iterpool));
 
       if (adm_subdir_kind == svn_node_dir)
         {
@@ -673,7 +678,7 @@ svn_wc__db_wcroot_parse_local_abspath(sv
           if (!moved_upwards || always_check)
             {
               SVN_ERR(get_old_version(&wc_format, local_abspath,
-                                      scratch_pool));
+                                      iterpool));
               if (wc_format != 0)
                 break;
             }
@@ -697,7 +702,7 @@ svn_wc__db_wcroot_parse_local_abspath(sv
 
               SVN_ERR(svn_io_check_resolved_path(local_abspath,
                                                  &resolved_kind,
-                                                 scratch_pool));
+                                                 iterpool));
               if (resolved_kind == svn_node_dir)
                 {
                   /* Is this directory recorded in our hash?  */
@@ -973,6 +978,7 @@ try_symlink_as_dir:
     }
   while (strcmp(scan_abspath, local_abspath) != 0);
 
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ra-git/subversion/libsvn_wc/wcroot_anchor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_wc/wcroot_anchor.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_wc/wcroot_anchor.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_wc/wcroot_anchor.c Wed Nov  7 12:30:06 2018
@@ -183,6 +183,29 @@ svn_wc__get_wcroot(const char **wcroot_a
 
 
 svn_error_t *
+svn_wc__get_shelves_dir(char **dir,
+                        svn_wc_context_t *wc_ctx,
+                        const char *local_abspath,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  const char *wcroot_abspath;
+
+  SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, wc_ctx, local_abspath,
+                             scratch_pool, scratch_pool));
+  *dir = svn_dirent_join(wcroot_abspath,
+                         SVN_WC_ADM_DIR_NAME "/" SVN_WC__ADM_EXPERIMENTAL "/"
+                           "shelves/v2",
+                         result_pool);
+  
+  /* Ensure the directory exists. (Other versions of svn don't create it.) */
+  SVN_ERR(svn_io_make_dir_recursively(*dir, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_wc_get_actual_target2(const char **anchor,
                           const char **target,
                           svn_wc_context_t *wc_ctx,

Modified: subversion/branches/ra-git/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_authz_svn/mod_authz_svn.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/ra-git/subversion/mod_authz_svn/mod_authz_svn.c Wed Nov  7 12:30:06 2018
@@ -154,7 +154,7 @@ canonicalize_access_file(const char *acc
     }
 
   /* We don't canonicalize repos relative urls since they get
-   * canonicalized before calling svn_repos_authz_read2() when they
+   * canonicalized before calling svn_repos_authz_read3() when they
    * are resolved. */
 
   return access_file;
@@ -472,10 +472,10 @@ get_access_conf(request_rec *r, authz_sv
   access_conf = user_data;
   if (access_conf == NULL)
     {
-
-      svn_err = svn_repos_authz_read2(&access_conf, access_file,
-                                      groups_file, TRUE,
-                                      r->connection->pool);
+      svn_err = svn_repos_authz_read3(&access_conf, access_file,
+                                      groups_file, TRUE, NULL,
+                                      r->connection->pool,
+                                      scratch_pool);
 
       if (svn_err)
         {
@@ -912,7 +912,7 @@ access_checker(request_rec *r)
         {
           /* Set the note to force authn regardless of what access_checker_ex
              hook requires */
-          apr_table_setn(r->notes, FORCE_AUTHN_NOTE, (const char*)1);
+          apr_table_setn(r->notes, FORCE_AUTHN_NOTE, "1");
 
           /* provide the proper return so the access_checker hook doesn't
            * prevent the code from continuing on to the other auth hooks */
@@ -978,7 +978,7 @@ access_checker(request_rec *r)
            * ap_some_authn_rquired() without triggering an infinite
            * loop since the call will trigger this function to be
            * called again. */
-          apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, (const char*)1);
+          apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, "1");
           authn_required = ap_some_authn_required(r);
           apr_table_unset(r->notes, IN_SOME_AUTHN_NOTE);
           if (authn_required)
@@ -1021,7 +1021,7 @@ check_user_id(request_rec *r)
   status = req_check_access(r, conf, &repos_path, &dest_repos_path);
   if (status == OK)
     {
-      apr_table_setn(r->notes, "authz_svn-anon-ok", (const char*)1);
+      apr_table_setn(r->notes, "authz_svn-anon-ok", "1");
       log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
       return OK;
     }