subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1662916 [4/15] - in /subversion/branches/1.9.x: ./ build/ build/generator/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subve...
Date Sat, 28 Feb 2015 10:37:30 GMT
Modified: subversion/branches/1.9.x/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/status.c?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/status.c Sat Feb 28 10:37:27 2015
@@ -53,6 +53,26 @@
 #include "private/svn_editor.h"
 
 
+/* The file internal variant of svn_wc_status3_t, with slightly more
+   data.
+
+   Instead of directly creating svn_wc_status3_t instances, we really
+   create instances of this struct with slightly more data for processing
+   by the status walker and status editor.
+
+   svn_wc_status3_dup() allocates space for this struct, but doesn't
+   copy the actual data. The remaining fields are copied by hash_stash(),
+   which is where the status editor stashes information for producing
+   later. */
+typedef struct svn_wc__internal_status_t
+{
+  svn_wc_status3_t s; /* First member; same pointer*/
+
+  svn_boolean_t has_descendants;
+
+  /* Make sure to update hash_stash() when adding values here */
+} svn_wc__internal_status_t;
+
 
 /*** Baton used for walking the local status */
 struct walk_status_baton
@@ -126,7 +146,7 @@ struct edit_baton
   const apr_array_header_t *ignores;
 
   /* Status item for the path represented by the anchor of the edit. */
-  svn_wc_status3_t *anchor_status;
+  svn_wc__internal_status_t *anchor_status;
 
   /* Was open_root() called for this edit drive? */
   svn_boolean_t root_opened;
@@ -275,63 +295,20 @@ get_repos_root_url_relpath(const char **
       *repos_root_url = apr_pstrdup(result_pool, parent_repos_root_url);
       *repos_uuid = apr_pstrdup(result_pool, parent_repos_uuid);
     }
-  else if (info->status == svn_wc__db_status_added)
-    {
-      SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
-                                       repos_relpath, repos_root_url,
-                                       repos_uuid, NULL, NULL, NULL, NULL,
-                                       db, local_abspath,
-                                       result_pool, scratch_pool));
-    }
-  else if (info->status == svn_wc__db_status_deleted
-           && !info->have_more_work
-           && info->have_base)
-    {
-      SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, repos_relpath,
-                                       repos_root_url, repos_uuid, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL,
-                                       db, local_abspath,
-                                       result_pool, scratch_pool));
-    }
-  else if (info->status == svn_wc__db_status_deleted)
-    {
-      const char *work_del_abspath;
-      const char *add_abspath;
-
-      /* Handles working DELETE and the special case where there is just
-         svn_wc__db_status_not_present in WORKING */
-
-      SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, &work_del_abspath, NULL,
-                                       db, local_abspath,
-                                       scratch_pool, scratch_pool));
-
-      /* The parent of what has been deleted must be added */
-      add_abspath = svn_dirent_dirname(work_del_abspath, scratch_pool);
-
-      SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, repos_relpath,
-                                       repos_root_url, repos_uuid, NULL,
-                                       NULL, NULL, NULL,
-                                       db, add_abspath,
-                                       result_pool, scratch_pool));
-
-      *repos_relpath = svn_relpath_join(*repos_relpath,
-                                        svn_dirent_skip_ancestor(
-                                              add_abspath,
-                                              local_abspath),
-                                        result_pool);
-    }
   else
     {
-      *repos_relpath = NULL;
-      *repos_root_url = NULL;
-      *repos_uuid = NULL;
+      SVN_ERR(svn_wc__db_read_repos_info(NULL,
+                                         repos_relpath, repos_root_url,
+                                         repos_uuid,
+                                         db, local_abspath,
+                                         result_pool, scratch_pool));
     }
+
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-internal_status(svn_wc_status3_t **status,
+internal_status(svn_wc__internal_status_t **status,
                 svn_wc__db_t *db,
                 const char *local_abspath,
                 svn_boolean_t check_working_copy,
@@ -358,7 +335,7 @@ internal_status(svn_wc_status3_t **statu
    The status struct's repos_lock field will be set to REPOS_LOCK.
 */
 static svn_error_t *
-assemble_status(svn_wc_status3_t **status,
+assemble_status(svn_wc__internal_status_t **status,
                 svn_wc__db_t *db,
                 const char *local_abspath,
                 const char *parent_repos_root_url,
@@ -373,14 +350,12 @@ assemble_status(svn_wc_status3_t **statu
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
+  svn_wc__internal_status_t *inner_stat;
   svn_wc_status3_t *stat;
   svn_boolean_t switched_p = FALSE;
   svn_boolean_t copied = FALSE;
   svn_boolean_t conflicted;
   const char *moved_from_abspath = NULL;
-  svn_filesize_t filesize = (dirent && (dirent->kind == svn_node_file))
-                                ? dirent->filesize
-                                : SVN_INVALID_FILESIZE;
 
   /* Defaults for two main variables. */
   enum svn_wc_status_kind node_status = svn_wc_status_normal;
@@ -628,7 +603,9 @@ assemble_status(svn_wc_status3_t **statu
 
   /* 6. Build and return a status structure. */
 
-  stat = apr_pcalloc(result_pool, sizeof(**status));
+  inner_stat = apr_pcalloc(result_pool, sizeof(*inner_stat));
+  stat = &inner_stat->s;
+  inner_stat->has_descendants = info->has_descendants;
 
   switch (info->kind)
     {
@@ -644,7 +621,22 @@ assemble_status(svn_wc_status3_t **statu
         stat->kind = svn_node_unknown;
     }
   stat->depth = info->depth;
-  stat->filesize = filesize;
+
+  if (dirent)
+    {
+      stat->filesize = (dirent->kind == svn_node_file)
+                            ? dirent->filesize
+                            : SVN_INVALID_FILESIZE;
+      stat->actual_kind = dirent->special ? svn_node_symlink
+                                          : dirent->kind;
+    }
+  else
+    {
+      stat->filesize = SVN_INVALID_FILESIZE;
+      stat->actual_kind = ignore_text_mods ? svn_node_unknown
+                                           : svn_node_none;
+    }
+
   stat->node_status = node_status;
   stat->text_status = text_status;
   stat->prop_status = prop_status;
@@ -702,7 +694,7 @@ assemble_status(svn_wc_status3_t **statu
 
   stat->file_external = info->file_external;
 
-  *status = stat;
+  *status = inner_stat;
 
   return SVN_NO_ERROR;
 }
@@ -716,7 +708,7 @@ assemble_status(svn_wc_status3_t **statu
    node_status to svn_wc_status_unversioned.
  */
 static svn_error_t *
-assemble_unversioned(svn_wc_status3_t **status,
+assemble_unversioned(svn_wc__internal_status_t **status,
                      svn_wc__db_t *db,
                      const char *local_abspath,
                      const svn_io_dirent2_t *dirent,
@@ -725,17 +717,30 @@ assemble_unversioned(svn_wc_status3_t **
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
 {
+  svn_wc__internal_status_t *inner_status;
   svn_wc_status3_t *stat;
 
   /* return a fairly blank structure. */
-  stat = apr_pcalloc(result_pool, sizeof(*stat));
+  inner_status = apr_pcalloc(result_pool, sizeof(*inner_status));
+  stat = &inner_status->s;
 
   /*stat->versioned = FALSE;*/
   stat->kind = svn_node_unknown; /* not versioned */
   stat->depth = svn_depth_unknown;
-  stat->filesize = (dirent && dirent->kind == svn_node_file)
-                        ? dirent->filesize
-                        : SVN_INVALID_FILESIZE;
+  if (dirent)
+    {
+      stat->actual_kind = dirent->special ? svn_node_symlink
+                                           : dirent->kind;
+      stat->filesize = (dirent->kind == svn_node_file)
+                            ? dirent->filesize
+                            : SVN_INVALID_FILESIZE;
+    }
+  else
+    {
+       stat->actual_kind = svn_node_none;
+       stat->filesize = SVN_INVALID_FILESIZE;
+    }
+
   stat->node_status = svn_wc_status_none;
   stat->text_status = svn_wc_status_none;
   stat->prop_status = svn_wc_status_none;
@@ -772,7 +777,7 @@ assemble_unversioned(svn_wc_status3_t **
   stat->conflicted = tree_conflicted;
   stat->changelist = NULL;
 
-  *status = stat;
+  *status = inner_status;
   return SVN_NO_ERROR;
 }
 
@@ -793,7 +798,7 @@ send_status_structure(const struct walk_
                       void *status_baton,
                       apr_pool_t *scratch_pool)
 {
-  svn_wc_status3_t *statstruct;
+  svn_wc__internal_status_t *statstruct;
   const svn_lock_t *repos_lock = NULL;
 
   /* Check for a repository lock. */
@@ -827,7 +832,8 @@ send_status_structure(const struct walk_
 
   if (statstruct && status_func)
     return svn_error_trace((*status_func)(status_baton, local_abspath,
-                                          statstruct, scratch_pool));
+                                          &statstruct->s,
+                                          scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -983,7 +989,7 @@ send_unversioned_item(const struct walk_
 {
   svn_boolean_t is_ignored;
   svn_boolean_t is_external;
-  svn_wc_status3_t *status;
+  svn_wc__internal_status_t *status;
   const char *base_name = svn_dirent_basename(local_abspath, NULL);
 
   is_ignored = svn_wc_match_ignore_list(base_name, patterns, scratch_pool);
@@ -995,12 +1001,12 @@ send_unversioned_item(const struct walk_
 
   is_external = is_external_path(wb->externals, local_abspath, scratch_pool);
   if (is_external)
-    status->node_status = svn_wc_status_external;
+    status->s.node_status = svn_wc_status_external;
 
   /* We can have a tree conflict on an unversioned path, i.e. an incoming
    * delete on a locally deleted path during an update. Don't ever ignore
    * those! */
-  if (status->conflicted)
+  if (status->s.conflicted)
     is_ignored = FALSE;
 
   /* If we aren't ignoring it, or if it's an externals path, pass this
@@ -1009,7 +1015,7 @@ send_unversioned_item(const struct walk_
       || !is_ignored
       || is_external)
     return svn_error_trace((*status_func)(status_baton, local_abspath,
-                                          status, scratch_pool));
+                                          &status->s, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1112,7 +1118,7 @@ one_child_status(const struct walk_statu
 
       /* Descend in subdirectories. */
       if (depth == svn_depth_infinity
-          && info->kind == svn_node_dir)
+          && info->has_descendants /* is dir, or was dir and tc descendants */)
         {
           SVN_ERR(get_dir_status(wb, local_abspath, TRUE,
                                  dir_repos_root_url, dir_repos_relpath,
@@ -1472,9 +1478,15 @@ hash_stash(void *baton,
 {
   apr_hash_t *stat_hash = baton;
   apr_pool_t *hash_pool = apr_hash_pool_get(stat_hash);
+  void *new_status = svn_wc_dup_status3(status, hash_pool);
+  const svn_wc__internal_status_t *old_status = (const void*)status;
+
+  /* Copy the internal/private data. */
+  svn_wc__internal_status_t *is = new_status;
+  is->has_descendants = old_status->has_descendants;
+
   assert(! svn_hash_gets(stat_hash, path));
-  svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path),
-                svn_wc_dup_status3(status, hash_pool));
+  svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path), new_status);
 
   return SVN_NO_ERROR;
 }
@@ -1539,6 +1551,7 @@ tweak_statushash(void *baton,
   /* If not, make it so. */
   if (! statstruct)
     {
+      svn_wc__internal_status_t *i_stat;
       /* If this item isn't being added, then we're most likely
          dealing with a non-recursive (or at least partially
          non-recursive) working copy.  Due to bugs in how the client
@@ -1554,8 +1567,9 @@ tweak_statushash(void *baton,
         return SVN_NO_ERROR;
 
       /* Use the public API to get a statstruct, and put it into the hash. */
-      SVN_ERR(internal_status(&statstruct, db, local_abspath,
+      SVN_ERR(internal_status(&i_stat, db, local_abspath,
                               check_working_copy, pool, scratch_pool));
+      statstruct = &i_stat->s;
       statstruct->repos_lock = repos_lock;
       svn_hash_sets(statushash, apr_pstrdup(pool, local_abspath), statstruct);
     }
@@ -1594,9 +1608,9 @@ tweak_statushash(void *baton,
             statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
 
           statstruct->repos_root_url =
-                              b->edit_baton->anchor_status->repos_root_url;
+                              b->edit_baton->anchor_status->s.repos_root_url;
           statstruct->repos_uuid =
-                              b->edit_baton->anchor_status->repos_uuid;
+                              b->edit_baton->anchor_status->s.repos_uuid;
         }
 
       /* The last committed date, and author for deleted items
@@ -1636,9 +1650,9 @@ tweak_statushash(void *baton,
         {
           statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
           statstruct->repos_root_url =
-                          b->edit_baton->anchor_status->repos_root_url;
+                          b->edit_baton->anchor_status->s.repos_root_url;
           statstruct->repos_uuid =
-                          b->edit_baton->anchor_status->repos_uuid;
+                          b->edit_baton->anchor_status->s.repos_uuid;
         }
       statstruct->ood_kind = b->ood_kind;
       if (b->ood_changed_author)
@@ -1654,7 +1668,7 @@ find_dir_repos_relpath(const struct dir_
 {
   /* If we have no name, we're the root, return the anchor URL. */
   if (! db->name)
-    return db->edit_baton->anchor_status->repos_relpath;
+    return db->edit_baton->anchor_status->s.repos_relpath;
   else
     {
       const char *repos_relpath;
@@ -1686,7 +1700,7 @@ make_dir_baton(void **dir_baton,
   struct edit_baton *eb = edit_baton;
   struct dir_baton *d;
   const char *local_abspath;
-  const svn_wc_status3_t *status_in_parent;
+  const svn_wc__internal_status_t *status_in_parent;
   apr_pool_t *dir_pool;
 
   if (parent_baton)
@@ -1745,8 +1759,7 @@ make_dir_baton(void **dir_baton,
     status_in_parent = eb->anchor_status;
 
   if (status_in_parent
-      && status_in_parent->versioned
-      && (status_in_parent->kind == svn_node_dir)
+      && (status_in_parent->has_descendants)
       && (! d->excluded)
       && (d->depth == svn_depth_unknown
           || d->depth == svn_depth_infinity
@@ -1758,9 +1771,9 @@ make_dir_baton(void **dir_baton,
       const apr_array_header_t *ignores = eb->ignores;
 
       SVN_ERR(get_dir_status(&eb->wb, local_abspath, TRUE,
-                             status_in_parent->repos_root_url,
+                             status_in_parent->s.repos_root_url,
                              NULL /*parent_repos_relpath*/,
-                             status_in_parent->repos_uuid,
+                             status_in_parent->s.repos_uuid,
                              NULL,
                              NULL /* dirent */, ignores,
                              d->depth == svn_depth_files
@@ -1775,7 +1788,7 @@ make_dir_baton(void **dir_baton,
       this_dir_status = svn_hash_gets(d->statii, d->local_abspath);
       if (this_dir_status && this_dir_status->versioned
           && (d->depth == svn_depth_unknown
-              || d->depth > status_in_parent->depth))
+              || d->depth > status_in_parent->s.depth))
         {
           d->depth = this_dir_status->depth;
         }
@@ -1821,10 +1834,11 @@ make_file_baton(struct dir_baton *parent
  * This implementation should match the filter in assemble_status()
  */
 static svn_boolean_t
-is_sendable_status(const svn_wc_status3_t *status,
+is_sendable_status(const svn_wc__internal_status_t *i_status,
                    svn_boolean_t no_ignore,
                    svn_boolean_t get_all)
 {
+  const svn_wc_status3_t *status = &i_status->s;
   /* If the repository status was touched at all, it's interesting. */
   if (status->repos_node_status != svn_wc_status_none)
     return TRUE;
@@ -1850,8 +1864,8 @@ is_sendable_status(const svn_wc_status3_
     return TRUE;
 
   /* If the text, property or tree state is interesting, send it. */
-  if ((status->node_status != svn_wc_status_none
-       && (status->node_status != svn_wc_status_normal)))
+  if ((status->node_status != svn_wc_status_none)
+       && (status->node_status != svn_wc_status_normal))
     return TRUE;
 
   /* If it's switched, send it. */
@@ -1934,14 +1948,14 @@ handle_statii(struct edit_baton *eb,
   for (hi = apr_hash_first(pool, statii); hi; hi = apr_hash_next(hi))
     {
       const char *local_abspath = apr_hash_this_key(hi);
-      svn_wc_status3_t *status = apr_hash_this_val(hi);
+      svn_wc__internal_status_t *status = apr_hash_this_val(hi);
 
       /* Clear the subpool. */
       svn_pool_clear(iterpool);
 
       /* Now, handle the status.  We don't recurse for svn_depth_immediates
          because we already have the subdirectories' statii. */
-      if (status->versioned && status->kind == svn_node_dir
+      if (status->has_descendants
           && (depth == svn_depth_unknown
               || depth == svn_depth_infinity))
         {
@@ -1957,9 +1971,9 @@ handle_statii(struct edit_baton *eb,
                                  iterpool));
         }
       if (dir_was_deleted)
-        status->repos_node_status = svn_wc_status_deleted;
+        status->s.repos_node_status = svn_wc_status_deleted;
       if (is_sendable_status(status, eb->no_ignore, eb->get_all))
-        SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, status,
+        SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, &status->s,
                                   iterpool));
     }
 
@@ -2159,17 +2173,17 @@ close_directory(void *dir_baton,
           /* We're editing the root dir of the WC.  As its repos
              status info isn't otherwise set, set it directly to
              trigger invocation of the status callback below. */
-          eb->anchor_status->repos_node_status = repos_node_status;
-          eb->anchor_status->repos_prop_status = repos_prop_status;
-          eb->anchor_status->repos_text_status = repos_text_status;
+          eb->anchor_status->s.repos_node_status = repos_node_status;
+          eb->anchor_status->s.repos_prop_status = repos_prop_status;
+          eb->anchor_status->s.repos_text_status = repos_text_status;
 
           /* If the root dir is out of date set the ood info directly too. */
-          if (db->ood_changed_rev != eb->anchor_status->revision)
+          if (db->ood_changed_rev != eb->anchor_status->s.revision)
             {
-              eb->anchor_status->ood_changed_rev = db->ood_changed_rev;
-              eb->anchor_status->ood_changed_date = db->ood_changed_date;
-              eb->anchor_status->ood_kind = db->ood_kind;
-              eb->anchor_status->ood_changed_author =
+              eb->anchor_status->s.ood_changed_rev = db->ood_changed_rev;
+              eb->anchor_status->s.ood_changed_date = db->ood_changed_date;
+              eb->anchor_status->s.ood_kind = db->ood_kind;
+              eb->anchor_status->s.ood_changed_author =
                 apr_pstrdup(pool, db->ood_changed_author);
             }
         }
@@ -2180,25 +2194,25 @@ close_directory(void *dir_baton,
   if (pb && ! db->excluded)
     {
       svn_boolean_t was_deleted = FALSE;
-      const svn_wc_status3_t *dir_status;
+      svn_wc__internal_status_t *dir_status;
 
       /* See if the directory was deleted or replaced. */
       dir_status = svn_hash_gets(pb->statii, db->local_abspath);
       if (dir_status &&
-          ((dir_status->repos_node_status == svn_wc_status_deleted)
-           || (dir_status->repos_node_status == svn_wc_status_replaced)))
+          ((dir_status->s.repos_node_status == svn_wc_status_deleted)
+           || (dir_status->s.repos_node_status == svn_wc_status_replaced)))
         was_deleted = TRUE;
 
       /* Now do the status reporting. */
       SVN_ERR(handle_statii(eb,
-                            dir_status ? dir_status->repos_root_url : NULL,
-                            dir_status ? dir_status->repos_relpath : NULL,
-                            dir_status ? dir_status->repos_uuid : NULL,
+                            dir_status ? dir_status->s.repos_root_url : NULL,
+                            dir_status ? dir_status->s.repos_relpath : NULL,
+                            dir_status ? dir_status->s.repos_uuid : NULL,
                             db->statii, was_deleted, db->depth, scratch_pool));
       if (dir_status && is_sendable_status(dir_status, eb->no_ignore,
                                            eb->get_all))
         SVN_ERR((eb->status_func)(eb->status_baton, db->local_abspath,
-                                  dir_status, scratch_pool));
+                                  &dir_status->s, scratch_pool));
       svn_hash_sets(pb->statii, db->local_abspath, NULL);
     }
   else if (! pb)
@@ -2207,13 +2221,12 @@ close_directory(void *dir_baton,
          target, we should only report the target. */
       if (*eb->target_basename)
         {
-          const svn_wc_status3_t *tgt_status;
+          const svn_wc__internal_status_t *tgt_status;
 
           tgt_status = svn_hash_gets(db->statii, eb->target_abspath);
           if (tgt_status)
             {
-              if (tgt_status->versioned
-                  && tgt_status->kind == svn_node_dir)
+              if (tgt_status->has_descendants)
                 {
                   SVN_ERR(get_dir_status(&eb->wb,
                                          eb->target_abspath, TRUE,
@@ -2228,7 +2241,7 @@ close_directory(void *dir_baton,
                 }
               if (is_sendable_status(tgt_status, eb->no_ignore, eb->get_all))
                 SVN_ERR((eb->status_func)(eb->status_baton, eb->target_abspath,
-                                          tgt_status, scratch_pool));
+                                          &tgt_status->s, scratch_pool));
             }
         }
       else
@@ -2237,15 +2250,15 @@ close_directory(void *dir_baton,
              Note that our directory couldn't have been deleted,
              because it is the root of the edit drive. */
           SVN_ERR(handle_statii(eb,
-                                eb->anchor_status->repos_root_url,
-                                eb->anchor_status->repos_relpath,
-                                eb->anchor_status->repos_uuid,
+                                eb->anchor_status->s.repos_root_url,
+                                eb->anchor_status->s.repos_relpath,
+                                eb->anchor_status->s.repos_uuid,
                                 db->statii, FALSE, eb->default_depth,
                                 scratch_pool));
           if (is_sendable_status(eb->anchor_status, eb->no_ignore,
                                  eb->get_all))
             SVN_ERR((eb->status_func)(eb->status_baton, db->local_abspath,
-                                      eb->anchor_status, scratch_pool));
+                                      &eb->anchor_status->s, scratch_pool));
           eb->anchor_status = NULL;
         }
     }
@@ -2666,7 +2679,7 @@ svn_wc__internal_walk_status(svn_wc__db_
     }
 
   if (info
-      && info->kind == svn_node_dir
+      && info->has_descendants /* is dir, or was dir and has tc descendants */
       && info->status != svn_wc__db_status_not_present
       && info->status != svn_wc__db_status_excluded
       && info->status != svn_wc__db_status_server_excluded)
@@ -2786,7 +2799,7 @@ svn_wc_get_default_ignores(apr_array_hea
 
 /* */
 static svn_error_t *
-internal_status(svn_wc_status3_t **status,
+internal_status(svn_wc__internal_status_t **status,
                 svn_wc__db_t *db,
                 const char *local_abspath,
                 svn_boolean_t check_working_copy,
@@ -2893,17 +2906,21 @@ svn_wc_status3(svn_wc_status3_t **status
                apr_pool_t *result_pool,
                apr_pool_t *scratch_pool)
 {
-  return svn_error_trace(
-      internal_status(status, wc_ctx->db, local_abspath,
-                      TRUE /* check_working_copy */,
-                      result_pool, scratch_pool));
+  svn_wc__internal_status_t *stat;
+  SVN_ERR(internal_status(&stat, wc_ctx->db, local_abspath,
+                          TRUE /* check_working_copy */,
+                          result_pool, scratch_pool));
+  *status = &stat->s;
+  return SVN_NO_ERROR;
 }
 
 svn_wc_status3_t *
 svn_wc_dup_status3(const svn_wc_status3_t *orig_stat,
                    apr_pool_t *pool)
 {
-  svn_wc_status3_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
+  /* Allocate slightly more room */
+  svn_wc__internal_status_t *new_istat = apr_palloc(pool, sizeof(*new_istat));
+  svn_wc_status3_t *new_stat = &new_istat->s;
 
   /* Shallow copy all members. */
   *new_stat = *orig_stat;

Modified: subversion/branches/1.9.x/subversion/libsvn_wc/translate.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/translate.c?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/translate.c (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/translate.c Sat Feb 28 10:37:27 2015
@@ -316,12 +316,15 @@ svn_wc__expand_keywords(apr_hash_t **key
                                    db, local_abspath,
                                    scratch_pool, scratch_pool));
 
-      if (repos_relpath)
-        url = svn_path_url_add_component2(repos_root_url, repos_relpath,
-                                          scratch_pool);
-      else
-         SVN_ERR(svn_wc__db_read_url(&url, db, local_abspath, scratch_pool,
-                                     scratch_pool));
+      /* Handle special statuses (e.g. added) */
+      if (!repos_relpath)
+         SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath,
+                                            &repos_root_url, NULL,
+                                            db, local_abspath,
+                                            scratch_pool, scratch_pool));
+
+      url = svn_path_url_add_component2(repos_root_url, repos_relpath,
+                                        scratch_pool);
     }
   else
     {

Modified: subversion/branches/1.9.x/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/update_editor.c?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/update_editor.c Sat Feb 28 10:37:27 2015
@@ -1310,99 +1310,6 @@ open_root(void *edit_baton,
 /* ===================================================================== */
 /* Checking for local modifications. */
 
-/* A baton for use with modcheck_found_entry(). */
-typedef struct modcheck_baton_t {
-  svn_wc__db_t *db;         /* wc_db to access nodes */
-  svn_boolean_t found_mod;  /* whether a modification has been found */
-  svn_boolean_t found_not_delete;  /* Found a not-delete modification */
-} modcheck_baton_t;
-
-/* An implementation of svn_wc_status_func4_t. */
-static svn_error_t *
-modcheck_callback(void *baton,
-                  const char *local_abspath,
-                  const svn_wc_status3_t *status,
-                  apr_pool_t *scratch_pool)
-{
-  modcheck_baton_t *mb = baton;
-
-  switch (status->node_status)
-    {
-      case svn_wc_status_normal:
-      case svn_wc_status_incomplete:
-      case svn_wc_status_ignored:
-      case svn_wc_status_none:
-      case svn_wc_status_unversioned:
-      case svn_wc_status_external:
-        break;
-
-      case svn_wc_status_deleted:
-        mb->found_mod = TRUE;
-        break;
-
-      case svn_wc_status_missing:
-      case svn_wc_status_obstructed:
-        mb->found_mod = TRUE;
-        mb->found_not_delete = TRUE;
-        /* Exit from the status walker: We know what we want to know */
-        return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
-
-      default:
-      case svn_wc_status_added:
-      case svn_wc_status_replaced:
-      case svn_wc_status_modified:
-        mb->found_mod = TRUE;
-        mb->found_not_delete = TRUE;
-        /* Exit from the status walker: We know what we want to know */
-        return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Set *MODIFIED to true iff there are any local modifications within the
- * tree rooted at LOCAL_ABSPATH, using DB. If *MODIFIED
- * is set to true and all the local modifications were deletes then set
- * *ALL_EDITS_ARE_DELETES to true, set it to false otherwise.  LOCAL_ABSPATH
- * may be a file or a directory. */
-svn_error_t *
-svn_wc__node_has_local_mods(svn_boolean_t *modified,
-                            svn_boolean_t *all_edits_are_deletes,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            svn_cancel_func_t cancel_func,
-                            void *cancel_baton,
-                            apr_pool_t *scratch_pool)
-{
-  modcheck_baton_t modcheck_baton = { NULL, FALSE, FALSE };
-  svn_error_t *err;
-
-  modcheck_baton.db = db;
-
-  /* Walk the WC tree for status with depth infinity, looking for any local
-   * modifications. If it's a "sparse" directory, that's OK: there can be
-   * no local mods in the pieces that aren't present in the WC. */
-
-  err = svn_wc__internal_walk_status(db, local_abspath,
-                                     svn_depth_infinity,
-                                     FALSE, FALSE, FALSE, NULL,
-                                     modcheck_callback, &modcheck_baton,
-                                     cancel_func, cancel_baton,
-                                     scratch_pool);
-
-  if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
-    svn_error_clear(err);
-  else
-    SVN_ERR(err);
-
-  *modified = modcheck_baton.found_mod;
-  *all_edits_are_deletes = (modcheck_baton.found_mod
-                            && !modcheck_baton.found_not_delete);
-
-  return SVN_NO_ERROR;
-}
-
 /* Indicates an unset svn_wc_conflict_reason_t. */
 #define SVN_WC_CONFLICT_REASON_NONE (svn_wc_conflict_reason_t)(-1)
 
@@ -1437,7 +1344,6 @@ check_tree_conflict(svn_skel_t **pconfli
 {
   svn_wc_conflict_reason_t reason = SVN_WC_CONFLICT_REASON_NONE;
   svn_boolean_t modified = FALSE;
-  svn_boolean_t all_mods_are_deletes = FALSE;
   const char *move_src_op_root_abspath = NULL;
 
   *pconflict = NULL;
@@ -1476,15 +1382,15 @@ check_tree_conflict(svn_skel_t **pconfli
           }
         else
           {
-            /* The node is locally replaced but could also be moved-away. */
-            SVN_ERR(svn_wc__db_base_moved_to(NULL, NULL, NULL,
-                                             &move_src_op_root_abspath,
-                                             eb->db, local_abspath,
-                                             scratch_pool, scratch_pool));
-            if (move_src_op_root_abspath)
-              reason = svn_wc_conflict_reason_moved_away;
-            else
-              reason = svn_wc_conflict_reason_replaced;
+            /* The node is locally replaced but could also be moved-away,
+               but we can't report that it is moved away and replaced.
+
+               And we wouldn't be able to store that each of a dozen
+               descendants was moved to other locations...
+
+               Replaced is what actually happened... */
+
+            reason = svn_wc_conflict_reason_replaced;
           }
         break;
 
@@ -1547,14 +1453,14 @@ check_tree_conflict(svn_skel_t **pconfli
          * not visit the subdirectories of a directory that it wants to delete.
          * Therefore, we need to start a separate crawl here. */
 
-        SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_mods_are_deletes,
-                                            eb->db, local_abspath,
+        SVN_ERR(svn_wc__node_has_local_mods(&modified, NULL,
+                                            eb->db, local_abspath, FALSE,
                                             eb->cancel_func, eb->cancel_baton,
                                             scratch_pool));
 
         if (modified)
           {
-            if (all_mods_are_deletes)
+            if (working_status == svn_wc__db_status_deleted)
               reason = svn_wc_conflict_reason_deleted;
             else
               reason = svn_wc_conflict_reason_edited;
@@ -1712,8 +1618,6 @@ delete_entry(const char *path,
   apr_pool_t *scratch_pool;
   svn_boolean_t deleting_target;
   svn_boolean_t deleting_switched;
-  svn_boolean_t keep_as_working = FALSE;
-  svn_boolean_t queue_deletes = TRUE;
 
   if (pb->skip_this)
     return SVN_NO_ERROR;
@@ -1806,11 +1710,9 @@ delete_entry(const char *path,
       || base_status == svn_wc__db_status_excluded
       || base_status == svn_wc__db_status_server_excluded)
     {
-      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
-                                     FALSE /* keep_as_working */,
-                                     FALSE /* queue_deletes */,
-                                     FALSE /* remove_locks */,
-                                     SVN_INVALID_REVNUM /* not_present_rev */,
+      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath, TRUE,
+                                     deleting_target, FALSE,
+                                     *eb->target_revision,
                                      NULL, NULL,
                                      scratch_pool));
 
@@ -1837,12 +1739,9 @@ delete_entry(const char *path,
                                   svn_wc_conflict_action_delete,
                                   pb->pool, scratch_pool));
     }
-  else
-    queue_deletes = FALSE; /* There is no in-wc representation */
 
   if (tree_conflict != NULL)
     {
-      svn_wc_conflict_reason_t reason;
       /* When we raise a tree conflict on a node, we don't want to mark the
        * node as skipped, to allow a replacement to continue doing at least
        * a bit of its work (possibly adding a not present node, for the
@@ -1853,37 +1752,8 @@ delete_entry(const char *path,
       svn_hash_sets(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
                     tree_conflict);
 
-      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
-                                                  eb->db, local_abspath,
-                                                  tree_conflict,
-                                                  scratch_pool, scratch_pool));
-
-      if (reason == svn_wc_conflict_reason_edited
-          || reason == svn_wc_conflict_reason_obstructed)
-        {
-          /* The item exists locally and has some sort of local mod.
-           * It no longer exists in the repository at its target URL@REV.
-           *
-           * To prepare the "accept mine" resolution for the tree conflict,
-           * we must schedule the existing content for re-addition as a copy
-           * of what it was, but with its local modifications preserved. */
-          keep_as_working = TRUE;
-
-          /* Fall through to remove the BASE_NODEs properly, with potentially
-             keeping a not-present marker */
-        }
-      else if (reason == svn_wc_conflict_reason_deleted
-               || reason == svn_wc_conflict_reason_moved_away
-               || reason == svn_wc_conflict_reason_replaced)
-        {
-          /* The item does not exist locally because it was already shadowed.
-           * We must complete the deletion, leaving the tree conflict info
-           * as the only difference from a normal deletion. */
-
-          /* Fall through to the normal "delete" code path. */
-        }
-      else
-        SVN_ERR_MALFUNCTION();  /* other reasons are not expected here */
+      /* Whatever the kind of conflict, we can just clear BASE
+         by turning whatever is there into a copy */
     }
 
   /* Calculate the repository-relative path of the entry which was
@@ -1909,7 +1779,8 @@ delete_entry(const char *path,
     {
       /* Delete, and do not leave a not-present node.  */
       SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
-                                     keep_as_working, queue_deletes, FALSE,
+                                     (tree_conflict != NULL),
+                                     FALSE, FALSE,
                                      SVN_INVALID_REVNUM /* not_present_rev */,
                                      tree_conflict, NULL,
                                      scratch_pool));
@@ -1918,7 +1789,8 @@ delete_entry(const char *path,
     {
       /* Delete, leaving a not-present node.  */
       SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
-                                     keep_as_working, queue_deletes, FALSE,
+                                     (tree_conflict != NULL),
+                                     TRUE, FALSE,
                                      *eb->target_revision,
                                      tree_conflict, NULL,
                                      scratch_pool));
@@ -4866,9 +4738,7 @@ close_edit(void *edit_baton,
                  If so, we should get rid of this excluded node now. */
 
               SVN_ERR(svn_wc__db_base_remove(eb->db, eb->target_abspath,
-                                             FALSE /* keep_as_working */,
-                                             FALSE /* queue_deletes */,
-                                             FALSE /* remove_locks */,
+                                             TRUE, FALSE, FALSE,
                                              SVN_INVALID_REVNUM,
                                              NULL, NULL, scratch_pool));
             }
@@ -5685,8 +5555,8 @@ svn_wc__complete_directory_add(svn_wc_co
                                    original_repos_relpath, original_root_url,
                                    original_uuid, original_revision,
                                    NULL /* children */,
-                                   FALSE /* is_move */,
                                    svn_depth_infinity,
+                                   FALSE /* is_move */,
                                    NULL /* conflict */,
                                    NULL /* work_items */,
                                    scratch_pool));

Modified: subversion/branches/1.9.x/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/upgrade.c?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/upgrade.c Sat Feb 28 10:37:27 2015
@@ -37,6 +37,7 @@
 #include "tree_conflicts.h"
 #include "wc-queries.h"  /* for STMT_*  */
 #include "workqueue.h"
+#include "token-map.h"
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
@@ -824,6 +825,190 @@ migrate_tree_conflict_data(svn_sqlite__d
   return SVN_NO_ERROR;
 }
 
+/* ### need much more docco
+
+   ### this function should be called within a sqlite transaction. it makes
+   ### assumptions around this fact.
+
+   Apply the various sets of properties to the database nodes based on
+   their existence/presence, the current state of the node, and the original
+   format of the working copy which provided these property sets.
+*/
+static svn_error_t *
+upgrade_apply_props(svn_sqlite__db_t *sdb,
+                    const char *dir_abspath,
+                    const char *local_relpath,
+                    apr_hash_t *base_props,
+                    apr_hash_t *revert_props,
+                    apr_hash_t *working_props,
+                    int original_format,
+                    apr_int64_t wc_id,
+                    apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  int top_op_depth = -1;
+  int below_op_depth = -1;
+  svn_wc__db_status_t top_presence;
+  svn_wc__db_status_t below_presence;
+  int affected_rows;
+
+  /* ### working_props: use set_props_txn.
+     ### if working_props == NULL, then skip. what if they equal the
+     ### pristine props? we should probably do the compare here.
+     ###
+     ### base props go into WORKING_NODE if avail, otherwise BASE.
+     ###
+     ### revert only goes into BASE. (and WORKING better be there!)
+
+     Prior to 1.4.0 (ORIGINAL_FORMAT < 8), REVERT_PROPS did not exist. If a
+     file was deleted, then a copy (potentially with props) was disallowed
+     and could not replace the deletion. An addition *could* be performed,
+     but that would never bring its own props.
+
+     1.4.0 through 1.4.5 created the concept of REVERT_PROPS, but had a
+     bug in svn_wc_add_repos_file2() whereby a copy-with-props did NOT
+     construct a REVERT_PROPS if the target had no props. Thus, reverting
+     the delete/copy would see no REVERT_PROPS to restore, leaving the
+     props from the copy source intact, and appearing as if they are (now)
+     the base props for the previously-deleted file. (wc corruption)
+
+     1.4.6 ensured that an empty REVERT_PROPS would be established at all
+     times. See issue 2530, and r861670 as starting points.
+
+     We will use ORIGINAL_FORMAT and SVN_WC__NO_REVERT_FILES to determine
+     the handling of our inputs, relative to the state of this node.
+  */
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_NODE_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    {
+      top_op_depth = svn_sqlite__column_int(stmt, 0);
+      top_presence = svn_sqlite__column_token(stmt, 3, presence_map);
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+      if (have_row)
+        {
+          below_presence = svn_sqlite__column_token(stmt, 3, presence_map);
+
+          /* There might be an intermediate layer on mixed-revision copies,
+             or when BASE is shadowed */
+          if (below_presence == svn_wc__db_status_not_present
+              || below_presence == svn_wc__db_status_deleted)
+            SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+          if (have_row)
+            {
+              below_presence = svn_sqlite__column_token(stmt, 3, presence_map);
+              below_op_depth = svn_sqlite__column_int(stmt, 0);
+            }
+        }
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  /* Detect the buggy scenario described above. We cannot upgrade this
+     working copy if we have no idea where BASE_PROPS should go.  */
+  if (original_format > SVN_WC__NO_REVERT_FILES
+      && revert_props == NULL
+      && top_op_depth != -1
+      && top_presence == svn_wc__db_status_normal
+      && below_op_depth != -1
+      && below_presence != svn_wc__db_status_not_present)
+    {
+      /* There should be REVERT_PROPS, so it appears that we just ran into
+         the described bug. Sigh.  */
+      return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                               _("The properties of '%s' are in an "
+                                 "indeterminate state and cannot be "
+                                 "upgraded. See issue #2530."),
+                               svn_dirent_local_style(
+                                 svn_dirent_join(dir_abspath, local_relpath,
+                                                 scratch_pool), scratch_pool));
+    }
+
+  /* Need at least one row, or two rows if there are revert props */
+  if (top_op_depth == -1
+      || (below_op_depth == -1 && revert_props))
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                             _("Insufficient NODES rows for '%s'"),
+                             svn_dirent_local_style(
+                               svn_dirent_join(dir_abspath, local_relpath,
+                                               scratch_pool), scratch_pool));
+
+  /* one row, base props only: upper row gets base props
+     two rows, base props only: lower row gets base props
+     two rows, revert props only: lower row gets revert props
+     two rows, base and revert props: upper row gets base, lower gets revert */
+
+
+  if (revert_props || below_op_depth == -1)
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                        STMT_UPDATE_NODE_PROPS));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd",
+                                wc_id, local_relpath, top_op_depth));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 4, base_props, scratch_pool));
+      SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+      SVN_ERR_ASSERT(affected_rows == 1);
+    }
+
+  if (below_op_depth != -1)
+    {
+      apr_hash_t *props = revert_props ? revert_props : base_props;
+
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                        STMT_UPDATE_NODE_PROPS));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd",
+                                wc_id, local_relpath, below_op_depth));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool));
+      SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+      SVN_ERR_ASSERT(affected_rows == 1);
+    }
+
+  /* If there are WORKING_PROPS, then they always go into ACTUAL_NODE.  */
+  if (working_props != NULL
+      && base_props != NULL)
+    {
+      apr_array_header_t *diffs;
+
+      SVN_ERR(svn_prop_diffs(&diffs, working_props, base_props, scratch_pool));
+
+      if (diffs->nelts == 0)
+        working_props = NULL; /* No differences */
+    }
+
+  if (working_props != NULL)
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                  STMT_UPDATE_ACTUAL_PROPS));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 3, working_props,
+                                          scratch_pool));
+      SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+      if (affected_rows == 0)
+        {
+          /* We have to insert a row in ACTUAL */
+
+          SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                            STMT_INSERT_ACTUAL_PROPS));
+          SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+          if (*local_relpath != '\0')
+            SVN_ERR(svn_sqlite__bind_text(stmt, 3,
+                                          svn_relpath_dirname(local_relpath,
+                                                              scratch_pool)));
+          SVN_ERR(svn_sqlite__bind_properties(stmt, 4, working_props,
+                                              scratch_pool));
+          return svn_error_trace(svn_sqlite__step_done(stmt));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 struct bump_baton {
   const char *wcroot_abspath;
@@ -899,7 +1084,7 @@ migrate_node_props(const char *dir_abspa
   SVN_ERR(read_propfile(&working_props, working_abspath,
                         scratch_pool, scratch_pool));
 
-  return svn_error_trace(svn_wc__db_upgrade_apply_props(
+  return svn_error_trace(upgrade_apply_props(
                             sdb, new_wcroot_abspath,
                             svn_relpath_join(dir_relpath, name, scratch_pool),
                             base_props, revert_props, working_props,
@@ -1671,6 +1856,43 @@ bump_to_31(void *baton,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+upgrade_apply_dav_cache(svn_sqlite__db_t *sdb,
+                        const char *dir_relpath,
+                        apr_int64_t wc_id,
+                        apr_hash_t *cache_values,
+                        apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_index_t *hi;
+  svn_sqlite__stmt_t *stmt;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                    STMT_UPDATE_BASE_NODE_DAV_CACHE));
+
+  /* Iterate over all the wcprops, writing each one to the wc_db. */
+  for (hi = apr_hash_first(scratch_pool, cache_values);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = apr_hash_this_key(hi);
+      apr_hash_t *props = apr_hash_this_val(hi);
+      const char *local_relpath;
+
+      svn_pool_clear(iterpool);
+
+      local_relpath = svn_relpath_join(dir_relpath, name, iterpool);
+
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, iterpool));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 
 struct upgrade_data_t {
   svn_sqlite__db_t *sdb;
@@ -1808,8 +2030,8 @@ upgrade_to_wcng(void **dir_baton,
         SVN_ERR(read_wcprops(&all_wcprops, dir_abspath,
                              scratch_pool, scratch_pool));
 
-      SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(data->sdb, dir_relpath,
-                                                 all_wcprops, scratch_pool));
+      SVN_ERR(upgrade_apply_dav_cache(data->sdb, dir_relpath, wc_id,
+                                      all_wcprops, scratch_pool));
     }
 
   /* Upgrade all the properties (including "this dir").
@@ -2144,40 +2366,6 @@ is_old_wcroot(const char *local_abspath,
     svn_dirent_local_style(parent_abspath, scratch_pool));
 }
 
-/* Data for upgrade_working_copy_txn(). */
-typedef struct upgrade_working_copy_baton_t
-{
-  svn_wc__db_t *db;
-  const char *dir_abspath;
-  svn_wc_upgrade_get_repos_info_t repos_info_func;
-  void *repos_info_baton;
-  apr_hash_t *repos_cache;
-  const struct upgrade_data_t *data;
-  svn_cancel_func_t cancel_func;
-  void *cancel_baton;
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-  apr_pool_t *result_pool;
-} upgrade_working_copy_baton_t;
-
-
-/* Helper for svn_wc_upgrade. Implements svn_sqlite__transaction_callback_t */
-static svn_error_t *
-upgrade_working_copy_txn(void *baton,
-                         svn_sqlite__db_t *sdb,
-                         apr_pool_t *scratch_pool)
-{
-  upgrade_working_copy_baton_t *b = baton;
-
-  /* Upgrade the pre-wcng into a wcng in a temporary location. */
-  return(upgrade_working_copy(NULL, b->db, b->dir_abspath,
-                              b->repos_info_func, b->repos_info_baton,
-                              b->repos_cache, b->data,
-                              b->cancel_func, b->cancel_baton,
-                              b->notify_func, b->notify_baton,
-                              b->result_pool, scratch_pool));
-}
-
 svn_error_t *
 svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                const char *local_abspath,
@@ -2197,7 +2385,6 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
   svn_wc_entry_t *this_dir;
   apr_hash_t *entries;
   const char *root_adm_abspath;
-  upgrade_working_copy_baton_t cb_baton;
   svn_error_t *err;
   int result_format;
   svn_boolean_t bumped_format;
@@ -2295,22 +2482,14 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
   SVN_ERR(svn_wc__db_wclock_obtain(db, data.root_abspath, 0, FALSE,
                                    scratch_pool));
 
-  cb_baton.db = db;
-  cb_baton.dir_abspath = local_abspath;
-  cb_baton.repos_info_func = repos_info_func;
-  cb_baton.repos_info_baton = repos_info_baton;
-  cb_baton.repos_cache = repos_cache;
-  cb_baton.data = &data;
-  cb_baton.cancel_func = cancel_func;
-  cb_baton.cancel_baton = cancel_baton;
-  cb_baton.notify_func = notify_func;
-  cb_baton.notify_baton = notify_baton;
-  cb_baton.result_pool = scratch_pool;
-
-  SVN_ERR(svn_sqlite__with_lock(data.sdb,
-                                upgrade_working_copy_txn,
-                                &cb_baton,
-                                scratch_pool));
+  SVN_SQLITE__WITH_LOCK(
+    upgrade_working_copy(NULL, db, local_abspath,
+                         repos_info_func, repos_info_baton,
+                         repos_cache, &data,
+                         cancel_func, cancel_baton,
+                         notify_func, notify_baton,
+                         scratch_pool, scratch_pool),
+    data.sdb);
 
   /* A workqueue item to move the pristine dir into place */
   pristine_from = svn_wc__adm_child(data.root_abspath, PRISTINE_STORAGE_RELPATH,

Modified: subversion/branches/1.9.x/subversion/libsvn_wc/wc-checks.sql
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/wc-checks.sql?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/wc-checks.sql (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/wc-checks.sql Sat Feb 28 10:37:27 2015
@@ -76,16 +76,25 @@ BEGIN
 END;
 
 -- STMT_STATIC_VERIFY
-SELECT local_relpath, op_depth, 'SV001: No ancestor in NODES'
+SELECT local_relpath, op_depth, 1, 'Invalid parent relpath set in NODES'
 FROM nodes n WHERE local_relpath != ''
- AND file_external IS NULL
- AND NOT EXISTS(SELECT 1 from nodes i
-                WHERE i.wc_id=n.wc_id
-                  AND i.local_relpath=n.parent_relpath)
+ AND (parent_relpath IS NULL
+      OR NOT IS_STRICT_DESCENDANT_OF(local_relpath, parent_relpath)
+      OR relpath_depth(local_relpath) != relpath_depth(parent_relpath)+1)
+
+UNION ALL
+
+SELECT local_relpath, -1, 2, 'Invalid parent relpath set in ACTUAL'
+FROM actual_node a WHERE local_relpath != ''
+ AND (parent_relpath IS NULL
+      OR NOT IS_STRICT_DESCENDANT_OF(local_relpath, parent_relpath)
+      OR relpath_depth(local_relpath) != relpath_depth(parent_relpath)+1)
 
 UNION ALL
 
-SELECT local_relpath, -1, 'SV002: No ancestor in ACTUAL'
+/* All ACTUAL nodes must have an equivalent NODE in NODES
+   or be only one level deep (delete-delete tc) */
+SELECT local_relpath, -1, 10, 'No ancestor in ACTUAL'
 FROM actual_node a WHERE local_relpath != ''
  AND NOT EXISTS(SELECT 1 from nodes i
                 WHERE i.wc_id=a.wc_id
@@ -95,14 +104,16 @@ FROM actual_node a WHERE local_relpath !
                   AND i.local_relpath=a.local_relpath)
 
 UNION ALL
-
-SELECT a.local_relpath, -1, 'SV003: Bad or Unneeded actual data'
+/* Verify if the ACTUAL data makes sense for the related node.
+   Only conflict data is valid if there is none */
+SELECT a.local_relpath, -1, 11, 'Bad or Unneeded actual data'
 FROM actual_node a
 LEFT JOIN nodes n on n.wc_id = a.wc_id AND n.local_relpath = a.local_relpath
    AND n.op_depth = (SELECT MAX(op_depth) from nodes i
                      WHERE i.wc_id=a.wc_id AND i.local_relpath=a.local_relpath)
 WHERE (a.properties IS NOT NULL
-       AND n.presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE))
+       AND (n.presence IS NULL
+            OR n.presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE)))
    OR (a.changelist IS NOT NULL AND (n.kind IS NOT NULL AND n.kind != MAP_FILE))
    OR (a.conflict_data IS NULL AND a.properties IS NULL AND a.changelist IS NULL)
  AND NOT EXISTS(SELECT 1 from nodes i
@@ -111,7 +122,20 @@ WHERE (a.properties IS NOT NULL
 
 UNION ALL
 
-SELECT local_relpath, op_depth, 'SV004: Unneeded node data'
+/* A parent node must exist for every normal node except the root.
+   That node must exist at a lower or equal op-depth */
+SELECT local_relpath, op_depth, 20, 'No ancestor in NODES'
+FROM nodes n WHERE local_relpath != ''
+ AND file_external IS NULL
+ AND NOT EXISTS(SELECT 1 from nodes i
+                WHERE i.wc_id=n.wc_id
+                  AND i.local_relpath=n.parent_relpath
+                  AND i.op_depth <= n.op_depth)
+
+UNION ALL
+/* If a node is not present in the working copy (normal, add, copy) it doesn't
+   have revision details stored on this record */
+SELECT local_relpath, op_depth, 21, 'Unneeded node data'
 FROM nodes
 WHERE presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE)
 AND (properties IS NOT NULL
@@ -128,10 +152,140 @@ AND (properties IS NOT NULL
      OR inherited_props IS NOT NULL)
 
 UNION ALL
-
-SELECT local_relpath, op_depth, 'SV005: Unneeded base-deleted node data'
+/* base-deleted nodes don't have a repository location. They are just
+   shadowing without a replacement */
+SELECT local_relpath, op_depth, 22, 'Unneeded base-deleted node data'
 FROM nodes
 WHERE presence IN (MAP_BASE_DELETED)
 AND (repos_id IS NOT NULL
      OR repos_path IS NOT NULL
-     OR revision IS NOT NULL)
\ No newline at end of file
+     OR revision IS NOT NULL)
+
+UNION ALL
+/* Verify if type specific data is set (or not set for wrong type) */
+SELECT local_relpath, op_depth, 23, 'Kind specific data invalid on normal'
+FROM nodes
+WHERE presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+AND (kind IS NULL
+     OR (repos_path IS NULL
+         AND (properties IS NOT NULL
+              OR changed_revision IS NOT NULL
+              OR changed_author IS NOT NULL
+              OR (changed_date IS NOT NULL AND changed_date != 0)))
+     OR (CASE WHEN kind = MAP_FILE AND repos_path IS NOT NULL
+                                   THEN checksum IS NULL
+                                   ELSE checksum IS NOT NULL END)
+     OR (CASE WHEN kind = MAP_DIR THEN depth IS NULL
+                                  ELSE depth IS NOT NULL END)
+     OR (CASE WHEN kind = MAP_SYMLINK THEN symlink_target IS NULL
+                                      ELSE symlink_target IS NOT NULL END))
+
+UNION ALL
+/* Local-adds are always their own operation (read: they don't have
+   op-depth descendants, nor are op-depth descendants */
+SELECT local_relpath, op_depth, 24, 'Invalid op-depth for local add'
+FROM nodes
+WHERE presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+  AND repos_path IS NULL
+  AND op_depth != relpath_depth(local_relpath)
+
+UNION ALL
+/* op-depth descendants are only valid if they have a direct parent
+   node at the same op-depth. Only certain types allow further
+   descendants */
+SELECT local_relpath, op_depth, 25, 'Node missing op-depth ancestor'
+FROM nodes n
+WHERE op_depth < relpath_depth(local_relpath)
+  AND file_external IS NULL
+  AND NOT EXISTS(SELECT 1 FROM nodes p
+                 WHERE p.wc_id=n.wc_id AND p.local_relpath=n.parent_relpath
+                   AND p.op_depth=n.op_depth
+                   AND (p.presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+                        OR (p.presence IN (MAP_BASE_DELETED, MAP_NOT_PRESENT)
+                            AND n.presence = MAP_BASE_DELETED)))
+
+UNION ALL
+/* Present op-depth descendants have the repository location implied by their
+   ancestor */
+SELECT n.local_relpath, n.op_depth, 26, 'Copied descendant mismatch'
+FROM nodes n
+JOIN nodes p
+  ON p.wc_id=n.wc_id AND p.local_relpath=n.parent_relpath
+  AND n.op_depth=p.op_depth
+WHERE n.op_depth > 0 AND n.presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+   AND (n.repos_id != p.repos_id
+        OR n.repos_path !=
+           RELPATH_SKIP_JOIN(n.parent_relpath, p.repos_path, n.local_relpath)
+        OR n.revision != p.revision
+        OR p.kind != MAP_DIR
+        OR n.moved_here IS NOT p.moved_here)
+
+UNION ALL
+/* Only certain presence values are valid as op-root.
+   Note that the wc-root always has presence normal or incomplete */
+SELECT n.local_relpath, n.op_depth, 27, 'Invalid op-root presence'
+FROM nodes n
+WHERE n.op_depth = relpath_depth(local_relpath)
+  AND presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE, MAP_BASE_DELETED)
+
+UNION ALL
+/* If a node is shadowed, all its present op-depth descendants
+   must be shadowed at the same op-depth as well */
+SELECT n.local_relpath, s.op_depth, 28, 'Incomplete shadowing'
+FROM nodes n
+JOIN nodes s ON s.wc_id=n.wc_id AND s.local_relpath=n.local_relpath
+ AND s.op_depth = relpath_depth(s.local_relpath)
+ AND s.op_depth = (SELECT MIN(op_depth) FROM nodes d
+                   WHERE d.wc_id=s.wc_id AND d.local_relpath=s.local_relpath
+                     AND d.op_depth > n.op_depth)
+WHERE n.presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+  AND EXISTS(SELECT 1
+             FROM nodes dn
+             WHERE dn.wc_id=n.wc_id AND dn.op_depth=n.op_depth
+               AND dn.presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+               AND IS_STRICT_DESCENDANT_OF(dn.local_relpath, n.local_relpath)
+               AND dn.file_external IS NULL
+               AND NOT EXISTS(SELECT 1
+                              FROM nodes ds
+                              WHERE ds.wc_id=n.wc_id AND ds.op_depth=s.op_depth
+                                AND ds.local_relpath=dn.local_relpath))
+
+UNION ALL
+/* A base-delete is only valid if it directly deletes a present node */
+SELECT s.local_relpath, s.op_depth, 29, 'Invalid base-delete'
+FROM nodes s
+LEFT JOIN nodes n ON n.wc_id=s.wc_id AND n.local_relpath=s.local_relpath
+ AND n.op_depth = (SELECT MAX(op_depth) FROM nodes d
+                   WHERE d.wc_id=s.wc_id AND d.local_relpath=s.local_relpath
+                     AND d.op_depth < s.op_depth)
+WHERE s.presence = MAP_BASE_DELETED
+  AND (n.presence IS NULL
+       OR n.presence NOT IN (MAP_NORMAL, MAP_INCOMPLETE)
+       /*OR n.kind != s.kind*/)
+
+UNION ALL
+/* Moves are stored in the working layers, not in BASE */
+SELECT n.local_relpath, n.op_depth, 30, 'Invalid data for BASE'
+FROM nodes n
+WHERE n.op_depth = 0
+  AND (n.moved_to IS NOT NULL
+       OR n.moved_here IS NOT NULL)
+
+UNION ALL
+/* If moved_here is set on an op-root, there must be a proper moved_to */
+SELECT d.local_relpath, d.op_depth, 60, 'Moved here without origin'
+FROM nodes d
+WHERE d.op_depth = relpath_depth(d.local_relpath)
+  AND d.moved_here IS NOT NULL
+  AND NOT EXISTS(SELECT 1 FROM nodes s
+                 WHERE s.wc_id = d.wc_id AND s.moved_to = d.local_relpath)
+
+UNION ALL
+/* If moved_to is set there should be an moved op root at the target */
+SELECT s.local_relpath, s.op_depth, 61, 'Moved to without target'
+FROM nodes s
+WHERE s.moved_to IS NOT NULL
+  AND NOT EXISTS(SELECT 1 FROM nodes d
+                 WHERE d.wc_id = s.wc_id AND d.local_relpath = s.moved_to
+                   AND d.op_depth = relpath_depth(d.local_relpath)
+                   AND d.moved_here =1 AND d.repos_path IS NOT NULL)

Modified: subversion/branches/1.9.x/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/wc-queries.sql?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/wc-queries.sql Sat Feb 28 10:37:27 2015
@@ -156,6 +156,7 @@ ORDER BY local_relpath DESC
 SELECT local_relpath, op_depth, presence, kind
 FROM nodes_current
 WHERE wc_id = ?1 AND parent_relpath = ?2
+ORDER BY local_relpath
 
 -- STMT_SELECT_ACTUAL_CHILDREN_INFO
 SELECT local_relpath, changelist, properties, conflict_data
@@ -184,16 +185,6 @@ INSERT OR REPLACE INTO nodes (
 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
         ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23)
 
--- STMT_SELECT_BASE_PRESENT
-SELECT local_relpath, kind FROM nodes n
-WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
-  AND op_depth = 0
-  AND presence in (MAP_NORMAL, MAP_INCOMPLETE)
-  AND NOT EXISTS(SELECT 1 FROM NODES w
-                 WHERE w.wc_id = ?1 AND w.local_relpath = n.local_relpath
-                   AND op_depth > 0)
-ORDER BY local_relpath DESC
-
 -- STMT_SELECT_WORKING_PRESENT
 SELECT local_relpath, kind, checksum, translated_size, last_mod_time
 FROM nodes n
@@ -233,6 +224,16 @@ WHERE wc_id = ?1 AND IS_STRICT_DESCENDAN
 
 -- STMT_DELETE_WORKING_BASE_DELETE
 DELETE FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2
+  AND presence = MAP_BASE_DELETED
+  AND op_depth > ?3
+  AND op_depth = (SELECT MIN(op_depth) FROM nodes n
+                    WHERE n.wc_id = ?1
+                      AND n.local_relpath = nodes.local_relpath
+                      AND op_depth > ?3)
+
+-- STMT_DELETE_WORKING_BASE_DELETE_RECURSIVE
+DELETE FROM nodes
 WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
   AND presence = MAP_BASE_DELETED
   AND op_depth > ?3
@@ -344,7 +345,8 @@ ORDER BY local_relpath
 -- STMT_SELECT_GE_OP_DEPTH_CHILDREN
 SELECT 1 FROM nodes
 WHERE wc_id = ?1 AND parent_relpath = ?2
-  AND (op_depth > ?3 OR (op_depth = ?3 AND presence != MAP_BASE_DELETED))
+  AND (op_depth > ?3 OR (op_depth = ?3
+                         AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)))
 UNION ALL
 SELECT 1 FROM ACTUAL_NODE a
 WHERE wc_id = ?1 AND parent_relpath = ?2
@@ -378,6 +380,7 @@ UPDATE NODES SET op_depth = 0,
                  revision = ?6,
                  dav_cache = NULL,
                  moved_here = NULL,
+                 moved_to = NULL,
                  presence = CASE presence
                               WHEN MAP_NORMAL THEN MAP_NORMAL
                               WHEN MAP_EXCLUDED THEN MAP_EXCLUDED
@@ -390,22 +393,30 @@ WHERE wc_id = ?1
 -- STMT_SELECT_NODE_CHILDREN
 /* Return all paths that are children of the directory (?1, ?2) in any
    op-depth, including children of any underlying, replaced directories. */
-SELECT local_relpath FROM nodes
+SELECT DISTINCT local_relpath FROM nodes
 WHERE wc_id = ?1 AND parent_relpath = ?2
+ORDER BY local_relpath
 
 -- STMT_SELECT_WORKING_CHILDREN
 /* Return all paths that are children of the working version of the
    directory (?1, ?2).  A given path is not included just because it is a
    child of an underlying (replaced) directory, it has to be in the
    working version of the directory. */
-SELECT local_relpath FROM nodes
+SELECT DISTINCT local_relpath FROM nodes
 WHERE wc_id = ?1 AND parent_relpath = ?2
   AND (op_depth > (SELECT MAX(op_depth) FROM nodes
                    WHERE wc_id = ?1 AND local_relpath = ?2)
        OR
        (op_depth = (SELECT MAX(op_depth) FROM nodes
                     WHERE wc_id = ?1 AND local_relpath = ?2)
-        AND presence != MAP_BASE_DELETED))
+        AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)))
+ORDER BY local_relpath
+
+-- STMT_SELECT_BASE_NOT_PRESENT_CHILDREN
+SELECT local_relpath FROM nodes
+WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0
+  AND presence = MAP_NOT_PRESENT
+ORDER BY local_relpath
 
 -- STMT_SELECT_NODE_PROPS
 SELECT properties, presence FROM nodes
@@ -452,25 +463,13 @@ SELECT dav_cache FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0
 
 -- STMT_SELECT_DELETION_INFO
-SELECT (SELECT b.presence FROM nodes AS b
-         WHERE b.wc_id = ?1 AND b.local_relpath = ?2 AND b.op_depth = 0),
-       work.presence, work.op_depth
-FROM nodes_current AS work
-WHERE work.wc_id = ?1 AND work.local_relpath = ?2 AND work.op_depth > 0
-LIMIT 1
-
--- STMT_SELECT_DELETION_INFO_SCAN
-/* ### FIXME.  moved.moved_to IS NOT NULL works when there is
- only one move but we need something else when there are several. */
-SELECT (SELECT b.presence FROM nodes AS b
-         WHERE b.wc_id = ?1 AND b.local_relpath = ?2 AND b.op_depth = 0),
-       work.presence, work.op_depth, moved.moved_to
-FROM nodes_current AS work
-LEFT OUTER JOIN nodes AS moved
-  ON moved.wc_id = work.wc_id
- AND moved.local_relpath = work.local_relpath
- AND moved.moved_to IS NOT NULL
-WHERE work.wc_id = ?1 AND work.local_relpath = ?2 AND work.op_depth > 0
+SELECT b.presence, w.presence, w.op_depth, w.moved_to
+FROM nodes w
+LEFT JOIN nodes b ON b.wc_id = ?1 AND b.local_relpath = ?2 AND b.op_depth = 0
+WHERE w.wc_id = ?1 AND w.local_relpath = ?2
+  AND w.op_depth = (SELECT MAX(op_depth) FROM nodes d
+                    WHERE d.wc_id = ?1 AND d.local_relpath = ?2
+                      AND d.op_depth > 0)
 LIMIT 1
 
 -- STMT_SELECT_MOVED_TO_NODE
@@ -850,6 +849,7 @@ WHERE wc_id = ?1
 UPDATE nodes SET depth = ?3
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0
   AND kind=MAP_DIR
+  AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)
 
 -- STMT_UPDATE_NODE_BASE_PRESENCE
 UPDATE nodes SET presence = ?3
@@ -954,6 +954,14 @@ SELECT local_dir_relpath FROM wc_lock
 WHERE wc_id = ?1
   AND IS_STRICT_DESCENDANT_OF(local_dir_relpath, ?2)
 
+-- STMT_FIND_CONFLICT_DESCENDANT
+SELECT 1 FROM actual_node
+WHERE wc_id = ?1
+  AND local_relpath > (?2 || '/')
+  AND local_relpath < (?2 || '0') /* '0' = ascii('/') +1 */
+  AND conflict_data IS NOT NULL
+LIMIT 1
+
 -- STMT_DELETE_WC_LOCK_ORPHAN
 DELETE FROM wc_lock
 WHERE wc_id = ?1 AND local_dir_relpath = ?2
@@ -1023,15 +1031,17 @@ WHERE wc_id = ?1
 ORDER BY local_relpath
 
 -- STMT_INSERT_WORKING_NODE_FROM_BASE_COPY
-INSERT INTO nodes (
+INSERT OR REPLACE INTO nodes (
     wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
     revision, presence, depth, kind, changed_revision, changed_date,
     changed_author, checksum, properties, translated_size, last_mod_time,
-    symlink_target )
+    symlink_target, moved_to )
 SELECT wc_id, local_relpath, ?3 /*op_depth*/, parent_relpath, repos_id,
     repos_path, revision, presence, depth, kind, changed_revision,
     changed_date, changed_author, checksum, properties, translated_size,
-    last_mod_time, symlink_target
+    last_mod_time, symlink_target,
+    (SELECT moved_to FROM nodes
+     WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3) moved_to
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0
 
@@ -1580,16 +1590,6 @@ WHERE wc_id = ?1
   AND repos_path IS NOT RELPATH_SKIP_JOIN(?2, ?3, local_relpath)
 LIMIT 1
 
--- STMT_SELECT_BASE_FILES_RECURSIVE
-SELECT local_relpath, translated_size, last_mod_time FROM nodes AS n
-WHERE wc_id = ?1
-  AND (local_relpath = ?2
-       OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
-  AND op_depth = 0
-  AND kind=MAP_FILE
-  AND presence=MAP_NORMAL
-  AND file_external IS NULL
-
 -- STMT_SELECT_MOVED_FROM_RELPATH
 SELECT local_relpath, op_depth FROM nodes
 WHERE wc_id = ?1 AND moved_to = ?2 AND op_depth > 0
@@ -1685,26 +1685,6 @@ WHERE wc_id = ?1
   AND moved_to IS NOT NULL
   AND NOT IS_STRICT_DESCENDANT_OF(moved_to, ?2)
 
-/* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SRC
-   but the passed op-depth is the depth of the shadowing node.
-
-   This version is slightly more efficient as the most inner query is
-   only executed once, but the Sqlite page cache makes the difference
-   not really measurable */
--- STMT_SELECT_MOVED_DESCENDANTS_SHD
-SELECT n.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to
-FROM nodes s
-JOIN nodes n ON n.wc_id = ?1 AND n.local_relpath = s.local_relpath
- AND n.op_depth=(SELECT MAX(d.op_depth)
-                 FROM nodes d
-                 WHERE d.wc_id = ?1 AND d.local_relpath = ?2
-                   AND d.op_depth < ?3)
-WHERE s.wc_id = ?1 AND s.op_depth = ?3
-  AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
-  AND s.moved_to IS NOT NULL
-
-/* This statement is very similar to STMT_SELECT_MOVED_DESCENDANTS_SHD,
-   but the passed op-depth is the depth of the node as it originally existed */
 -- STMT_SELECT_MOVED_DESCENDANTS_SRC
 SELECT s.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to
 FROM nodes n
@@ -1715,7 +1695,7 @@ JOIN nodes s ON s.wc_id = n.wc_id AND s.
                       AND d.local_relpath = s.local_relpath
                       AND d.op_depth > ?3)
 WHERE n.wc_id = ?1 AND n.op_depth = ?3
-  AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
+  AND (n.local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2))
   AND s.moved_to IS NOT NULL
 
 -- STMT_COMMIT_UPDATE_ORIGIN

Modified: subversion/branches/1.9.x/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/libsvn_wc/wc.h?rev=1662916&r1=1662915&r2=1662916&view=diff
==============================================================================
--- subversion/branches/1.9.x/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/1.9.x/subversion/libsvn_wc/wc.h Sat Feb 28 10:37:27 2015
@@ -577,17 +577,6 @@ svn_wc__internal_get_origin(svn_boolean_
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);
 
-/* Internal version of svn_wc__node_get_repos_info() */
-svn_error_t *
-svn_wc__internal_get_repos_info(svn_revnum_t *revision,
-                                const char **repos_relpath,
-                                const char **repos_root_url,
-                                const char **repos_uuid,
-                                svn_wc__db_t *db,
-                                const char *local_abspath,
-                                apr_pool_t *result_pool,
-                                apr_pool_t *scratch_pool);
-
 /* Upgrade the wc sqlite database given in SDB for the wc located at
    WCROOT_ABSPATH. It's current/starting format is given by START_FORMAT.
    After the upgrade is complete (to as far as the automatic upgrade will
@@ -733,6 +722,7 @@ svn_wc__node_has_local_mods(svn_boolean_
                             svn_boolean_t *all_edits_are_deletes,
                             svn_wc__db_t *db,
                             const char *local_abspath,
+                            svn_boolean_t ignore_unversioned,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
                             apr_pool_t *scratch_pool);



Mime
View raw message