subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1449262 [12/25] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/ note...
Date Sat, 23 Feb 2013 01:25:44 GMT
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c Sat Feb 23 01:25:38 2013
@@ -284,6 +284,8 @@ remember_skipped_tree(struct edit_baton 
   return SVN_NO_ERROR;
 }
 
+/* Per directory baton. Lives in its own subpool of the parent directory
+   or of the edit baton if there is no parent directory */
 struct dir_baton
 {
   /* Basename of this directory. */
@@ -381,26 +383,10 @@ struct dir_baton
 
   /* The pool in which this baton itself is allocated. */
   apr_pool_t *pool;
-};
-
-
-/* The bump information is tracked separately from the directory batons.
-   This is a small structure kept in the edit pool, while the heavier
-   directory baton is managed by the editor driver.
-
-   In a postfix delta case, the directory batons are going to disappear.
-   The files will refer to these structures, rather than the full
-   directory baton.  */
-struct bump_dir_info
-{
-  /* ptr to the bump information for the parent directory */
-  struct bump_dir_info *parent;
 
-  /* how many entries are referring to this bump information? */
+  /* how many nodes are referring to baton? */
   int ref_count;
 
-  /* Pool that should be cleared after the dir is bumped */
-  apr_pool_t *pool;
 };
 
 
@@ -514,7 +500,6 @@ make_dir_baton(struct dir_baton **d_p,
 {
   apr_pool_t *dir_pool;
   struct dir_baton *d;
-  struct bump_dir_info *bdi;
 
   if (pb != NULL)
     dir_pool = svn_pool_create(pb->pool);
@@ -599,23 +584,13 @@ make_dir_baton(struct dir_baton **d_p,
         }
     }
 
-  /* the bump information lives in the edit pool */
-  bdi = apr_pcalloc(dir_pool, sizeof(*bdi));
-  bdi->parent = pb ? pb->bump_info : NULL;
-  bdi->ref_count = 1;
-  bdi->pool = dir_pool;
-
-  /* the parent's bump info has one more referer */
-  if (pb)
-    ++bdi->parent->ref_count;
-
   d->edit_baton   = eb;
   d->parent_baton = pb;
   d->pool         = dir_pool;
   d->propchanges  = apr_array_make(dir_pool, 1, sizeof(svn_prop_t));
   d->obstruction_found = FALSE;
   d->add_existed  = FALSE;
-  d->bump_info    = bdi;
+  d->ref_count = 1;
   d->old_revision = SVN_INVALID_REVNUM;
   d->adding_dir   = adding;
   d->changed_rev  = SVN_INVALID_REVNUM;
@@ -626,6 +601,9 @@ make_dir_baton(struct dir_baton **d_p,
     {
       d->skip_this = pb->skip_this;
       d->shadowed = pb->shadowed || pb->edit_obstructed;
+
+      /* the parent's bump info has one more referer */
+      pb->ref_count++;
     }
 
   /* The caller of this function needs to fill these in. */
@@ -663,34 +641,32 @@ do_notification(const struct edit_baton 
   (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
 }
 
-/* Decrement the bump_dir_info's reference count. If it hits zero,
+/* Decrement the directory's reference count. If it hits zero,
    then this directory is "done". This means it is safe to clear its pool.
 
-   In addition, when the directory is "done", we loop onto the parent's
-   bump information to possibly mark it as done, too.
+   In addition, when the directory is "done", we recurse to possible cleanup
+   the parent directory.
 */
 static svn_error_t *
-maybe_release_dir_info(struct bump_dir_info *bdi)
+maybe_release_dir_info(struct dir_baton *db)
 {
-  /* Keep moving up the tree of directories until we run out of parents,
-     or a directory is not yet "done".  */
-  while (bdi != NULL)
-    {
-      apr_pool_t *destroy_pool;
+  db->ref_count--;
 
-      if (--bdi->ref_count > 0)
-        break;  /* directory isn't done yet */
+  if (!db->ref_count)
+    {
+      struct dir_baton *pb = db->parent_baton;
 
-      destroy_pool = bdi->pool;
-      bdi = bdi->parent;
+      svn_pool_destroy(db->pool);
 
-      svn_pool_destroy(destroy_pool);
+      if (pb)
+        SVN_ERR(maybe_release_dir_info(pb));
     }
-  /* we exited the for loop because there are no more parents */
 
   return SVN_NO_ERROR;
 }
 
+/* Per file baton. Lives in its own subpool below the pool of the parent
+   directory */
 struct file_baton
 {
   /* Pool specific to this file_baton. */
@@ -842,8 +818,8 @@ make_file_baton(struct file_baton **f_p,
   f->dir_baton         = pb;
   f->changed_rev       = SVN_INVALID_REVNUM;
 
-  /* the directory's bump info has one more referer now */
-  ++f->bump_info->ref_count;
+  /* the directory has one more referer now */
+  pb->ref_count++;
 
   *f_p = f;
   return SVN_NO_ERROR;
@@ -859,7 +835,7 @@ make_file_baton(struct file_baton **f_p,
  */
 static svn_error_t *
 complete_conflict(svn_skel_t *conflict,
-                  const struct dir_baton *pb,
+                  const struct edit_baton *eb,
                   const char *local_abspath,
                   const char *old_repos_relpath,
                   svn_revnum_t old_revision,
@@ -869,7 +845,6 @@ complete_conflict(svn_skel_t *conflict,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
-  const struct edit_baton *eb = pb->edit_baton;
   svn_wc_conflict_version_t *original_version;
   svn_wc_conflict_version_t *target_version;
   svn_boolean_t is_complete;
@@ -934,7 +909,7 @@ mark_directory_edited(struct dir_baton *
     {
       /* We have a (delayed) tree conflict to install */
 
-      SVN_ERR(complete_conflict(db->edit_conflict, db->parent_baton,
+      SVN_ERR(complete_conflict(db->edit_conflict, db->edit_baton,
                                 db->local_abspath,
                                 db->old_repos_relpath, db->old_revision,
                                 db->new_relpath,
@@ -969,7 +944,7 @@ mark_file_edited(struct file_baton *fb, 
     {
       /* We have a (delayed) tree conflict to install */
 
-      SVN_ERR(complete_conflict(fb->edit_conflict, fb->dir_baton,
+      SVN_ERR(complete_conflict(fb->edit_conflict, fb->edit_baton,
                                 fb->local_abspath, fb->old_repos_relpath,
                                 fb->old_revision, fb->new_relpath,
                                 svn_node_file, svn_node_file,
@@ -1145,6 +1120,15 @@ path_join_under_root(const char **result
                                  pool));
     }
 
+  /* This catches issue #3288 */
+  if (strcmp(add_path, svn_dirent_basename(*result_path, NULL)) != 0)
+    {
+      return svn_error_createf(
+          SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+          _("'%s' is not valid as filename in a working copy path"),
+          svn_dirent_local_style(add_path, pool));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1163,6 +1147,17 @@ set_target_revision(void *edit_baton,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+check_tree_conflict(svn_skel_t **pconflict,
+                    struct edit_baton *eb,
+                    const char *local_abspath,
+                    svn_wc__db_status_t working_status,
+                    svn_boolean_t exists_in_repos,
+                    svn_node_kind_t expected_kind,
+                    svn_wc_conflict_action_t action,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool);
+
 /* An svn_delta_editor_t function. */
 static svn_error_t *
 open_root(void *edit_baton,
@@ -1198,6 +1193,11 @@ open_root(void *edit_baton,
     }
   else if (already_conflicted)
     {
+      /* Record a skip of both the anchor and target in the skipped tree
+         as the anchor itself might not be updated */
+      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
+      SVN_ERR(remember_skipped_tree(eb, eb->target_abspath, pool));
+
       db->skip_this = TRUE;
       db->already_notified = TRUE;
 
@@ -1221,8 +1221,50 @@ open_root(void *edit_baton,
                                db->pool, pool));
 
   if (have_work)
-    db->shadowed = TRUE; /* Needed for the close_directory() on the root, to
-                            make sure it doesn't use the ACTUAL tree */
+    {
+      const char *move_src_root_abspath;
+
+      SVN_ERR(svn_wc__db_base_moved_to(NULL, NULL, &move_src_root_abspath,
+                                       NULL, eb->db, db->local_abspath,
+                                       pool, pool));
+      if (move_src_root_abspath)
+        {
+          /* This is an update anchored inside a move. We need to
+             raise a move-edit tree-conflict on the move root to
+             update the move destination. */
+          svn_skel_t *tree_conflict = svn_wc__conflict_skel_create(pool);
+
+          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                    tree_conflict, eb->db, move_src_root_abspath,
+                    svn_wc_conflict_reason_moved_away,
+                    svn_wc_conflict_action_edit,
+                    move_src_root_abspath, pool, pool));
+
+          if (strcmp(db->local_abspath, move_src_root_abspath))
+            {
+              /* This is some parent of the edit root, we won't be
+                 handling it again so raise the conflict now. */
+              SVN_ERR(complete_conflict(tree_conflict, eb,
+                                        move_src_root_abspath,
+                                        db->old_repos_relpath,
+                                        db->old_revision, db->new_relpath,
+                                        svn_node_dir, svn_node_dir,
+                                        pool, pool));
+              SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
+                                                  move_src_root_abspath,
+                                                  tree_conflict,
+                                                  NULL, pool));
+              do_notification(eb, move_src_root_abspath, svn_node_dir,
+                              svn_wc_notify_tree_conflict, pool);
+            }
+          else
+            db->edit_conflict = tree_conflict;
+        }
+
+
+      db->shadowed = TRUE; /* Needed for the close_directory() on the root, to
+                              make sure it doesn't use the ACTUAL tree */
+    }
 
   if (*eb->target_basename == '\0')
     {
@@ -1353,7 +1395,8 @@ svn_wc__node_has_local_mods(svn_boolean_
     SVN_ERR(err);
 
   *modified = modcheck_baton.found_mod;
-  *all_edits_are_deletes = !modcheck_baton.found_not_delete;
+  *all_edits_are_deletes = (modcheck_baton.found_mod
+                            && !modcheck_baton.found_not_delete);
 
   return SVN_NO_ERROR;
 }
@@ -1393,6 +1436,7 @@ 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;
 
@@ -1430,21 +1474,26 @@ check_tree_conflict(svn_skel_t **pconfli
           }
         else
           {
-            /* The node is locally replaced. */
-            reason = svn_wc_conflict_reason_replaced;
+            /* 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;
           }
         break;
 
 
       case svn_wc__db_status_deleted:
         {
-          const char *moved_to_abspath;
-
-          SVN_ERR(svn_wc__db_scan_deletion(NULL, &moved_to_abspath,
-                                           NULL, NULL, eb->db,
-                                           local_abspath,
+          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 (moved_to_abspath)
+          if (move_src_op_root_abspath)
             reason = svn_wc_conflict_reason_moved_away;
           else
             reason = svn_wc_conflict_reason_deleted;
@@ -1559,6 +1608,7 @@ check_tree_conflict(svn_skel_t **pconfli
                                                   eb->db, local_abspath,
                                                   reason,
                                                   action,
+                                                  move_src_op_root_abspath,
                                                   result_pool, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -1722,7 +1772,9 @@ delete_entry(const char *path,
     deleting_switched = FALSE;
 
   /* Is this path a conflict victim? */
-  if (conflicted)
+  if (pb->shadowed)
+    conflicted = FALSE; /* Conflict applies to WORKING */
+  else if (conflicted)
     SVN_ERR(node_already_conflicted(&conflicted, eb->db, local_abspath,
                                     scratch_pool));
   if (conflicted)
@@ -1740,8 +1792,8 @@ delete_entry(const char *path,
 
 
 
-    /* Receive the remote removal of excluded/server-excluded/not present node.
-       Do not notify, but perform the change even when the node is shadowed */
+  /* Receive the remote removal of excluded/server-excluded/not present node.
+     Do not notify, but perform the change even when the node is shadowed */
   if (base_status == svn_wc__db_status_not_present
       || base_status == svn_wc__db_status_excluded
       || base_status == svn_wc__db_status_server_excluded)
@@ -1794,7 +1846,7 @@ delete_entry(const char *path,
       apr_hash_set(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
                    APR_HASH_KEY_STRING, tree_conflict);
 
-      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
                                                   eb->db, local_abspath,
                                                   tree_conflict,
                                                   scratch_pool, scratch_pool));
@@ -1827,7 +1879,7 @@ delete_entry(const char *path,
         SVN_ERR_MALFUNCTION();  /* other reasons are not expected here */
     }
 
-  SVN_ERR(complete_conflict(tree_conflict, pb, local_abspath, repos_relpath,
+  SVN_ERR(complete_conflict(tree_conflict, eb, local_abspath, repos_relpath,
                             old_revision, NULL,
                             (kind == svn_kind_dir)
                                 ? svn_node_dir
@@ -2050,7 +2102,7 @@ add_directory(const char *path,
           /* ### Should store the conflict in DB to allow reinstalling
              ### with theoretically more data in close_directory() */
 
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
                                                       eb->db,
                                                       db->local_abspath,
                                                       tree_conflict,
@@ -2062,6 +2114,7 @@ add_directory(const char *path,
                                         tree_conflict,
                                         eb->db, db->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
+                                        NULL,
                                         db->pool, db->pool));
 
           /* And now stop checking for conflicts here and just perform
@@ -2186,14 +2239,14 @@ add_directory(const char *path,
                                         tree_conflict,
                                         eb->db, db->local_abspath,
                                         svn_wc_conflict_reason_unversioned,
-                                        svn_wc_conflict_action_add,
+                                        svn_wc_conflict_action_add, NULL,
                                         db->pool, pool));
           db->edit_conflict = tree_conflict;
         }
     }
 
   if (tree_conflict)
-    SVN_ERR(complete_conflict(tree_conflict, pb, db->local_abspath,
+    SVN_ERR(complete_conflict(tree_conflict, eb, db->local_abspath,
                               db->old_repos_relpath, db->old_revision,
                               db->new_relpath,
                               svn__node_kind_from_kind(wc_kind),
@@ -2321,7 +2374,9 @@ open_directory(const char *path,
   db->was_incomplete = (base_status == svn_wc__db_status_incomplete);
 
   /* Is this path a conflict victim? */
-  if (conflicted)
+  if (db->shadowed)
+    conflicted = FALSE; /* Conflict applies to WORKING */
+  else if (conflicted)
     SVN_ERR(node_already_conflicted(&conflicted, eb->db,
                                     db->local_abspath, pool));
   if (conflicted)
@@ -2355,7 +2410,7 @@ open_directory(const char *path,
       db->edit_conflict = tree_conflict;
       /* Other modifications wouldn't be a tree conflict */
 
-      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
                                                   eb->db, db->local_abspath,
                                                   tree_conflict,
                                                   db->pool, db->pool));
@@ -2451,7 +2506,7 @@ close_directory(void *dir_baton,
   if (db->skip_this)
     {
       /* Allow the parent to complete its update. */
-      SVN_ERR(maybe_release_dir_info(db->bump_info));
+      SVN_ERR(maybe_release_dir_info(db));
 
       return SVN_NO_ERROR;
     }
@@ -2769,7 +2824,7 @@ close_directory(void *dir_baton,
           svn_skel_t *work_item;
 
           SVN_ERR(complete_conflict(conflict_skel,
-                                    db->parent_baton,
+                                    db->edit_baton,
                                     db->local_abspath,
                                     db->old_repos_relpath,
                                     db->old_revision,
@@ -2867,7 +2922,7 @@ close_directory(void *dir_baton,
 
   /* We're done with this directory, so remove one reference from the
      bump information. */
-  SVN_ERR(maybe_release_dir_info(db->bump_info));
+  SVN_ERR(maybe_release_dir_info(db));
 
   return SVN_NO_ERROR;
 }
@@ -3120,7 +3175,9 @@ add_file(const char *path,
 
 
   /* Is this path a conflict victim? */
-  if (conflicted)
+  if (fb->shadowed)
+    conflicted = FALSE; /* Conflict applies to WORKING */
+  else if (conflicted)
     {
       if (pb->deletion_conflicts)
         tree_conflict = apr_hash_get(pb->deletion_conflicts, fb->name,
@@ -3135,7 +3192,7 @@ add_file(const char *path,
           /* ### Should store the conflict in DB to allow reinstalling
              ### with theoretically more data in close_directory() */
 
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
                                                       eb->db,
                                                       fb->local_abspath,
                                                       tree_conflict,
@@ -3147,6 +3204,7 @@ add_file(const char *path,
                                         tree_conflict,
                                         eb->db, fb->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
+                                        NULL,
                                         fb->pool, fb->pool));
 
           /* And now stop checking for conflicts here and just perform
@@ -3269,6 +3327,7 @@ add_file(const char *path,
                                         eb->db, fb->local_abspath,
                                         svn_wc_conflict_reason_unversioned,
                                         svn_wc_conflict_action_add,
+                                        NULL,
                                         fb->pool, scratch_pool));
         }
     }
@@ -3287,7 +3346,7 @@ add_file(const char *path,
   if (tree_conflict != NULL)
     {
       SVN_ERR(complete_conflict(tree_conflict,
-                                fb->dir_baton,
+                                fb->edit_baton,
                                 fb->local_abspath,
                                 fb->old_repos_relpath,
                                 fb->old_revision,
@@ -3385,7 +3444,9 @@ open_file(const char *path,
                                      fb->pool, scratch_pool));
 
   /* Is this path a conflict victim? */
-  if (conflicted)
+  if (fb->shadowed)
+    conflicted = FALSE; /* Conflict applies to WORKING */
+  else if (conflicted)
     SVN_ERR(node_already_conflicted(&conflicted, eb->db,
                                     fb->local_abspath, pool));
   if (conflicted)
@@ -3418,7 +3479,7 @@ open_file(const char *path,
       fb->edit_conflict = tree_conflict;
       /* Other modifications wouldn't be a tree conflict */
 
-      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+      SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
                                                   eb->db, fb->local_abspath,
                                                   tree_conflict,
                                                   scratch_pool, scratch_pool));
@@ -3654,9 +3715,10 @@ change_file_prop(void *file_baton,
                                      eb->db, fb->local_abspath,
                                      svn_wc_conflict_reason_edited,
                                      svn_wc_conflict_action_replace,
+                                     NULL,
                                      fb->pool, scratch_pool));
 
-          SVN_ERR(complete_conflict(fb->edit_conflict, fb->dir_baton,
+          SVN_ERR(complete_conflict(fb->edit_conflict, fb->edit_baton,
                                     fb->local_abspath, fb->old_repos_relpath,
                                     fb->old_revision, fb->new_relpath,
                                     svn_node_file, svn_node_file,
@@ -4039,6 +4101,7 @@ close_file(void *file_baton,
            apr_pool_t *pool)
 {
   struct file_baton *fb = file_baton;
+  struct dir_baton *pdb = fb->dir_baton;
   struct edit_baton *eb = fb->edit_baton;
   svn_wc_notify_state_t content_state, prop_state;
   svn_wc_notify_lock_state_t lock_state;
@@ -4061,8 +4124,8 @@ close_file(void *file_baton,
 
   if (fb->skip_this)
     {
-      SVN_ERR(maybe_release_dir_info(fb->bump_info));
       svn_pool_destroy(fb->pool);
+      SVN_ERR(maybe_release_dir_info(pdb));
       return SVN_NO_ERROR;
     }
 
@@ -4244,8 +4307,8 @@ close_file(void *file_baton,
                                             scratch_pool));
               fb->skip_this = TRUE;
 
-              SVN_ERR(maybe_release_dir_info(fb->bump_info));
               svn_pool_destroy(fb->pool);
+              SVN_ERR(maybe_release_dir_info(pdb));
               return SVN_NO_ERROR;
             }
           else
@@ -4366,7 +4429,7 @@ close_file(void *file_baton,
   if (conflict_skel)
     {
       SVN_ERR(complete_conflict(conflict_skel,
-                                fb->dir_baton,
+                                fb->edit_baton,
                                 fb->local_abspath,
                                 fb->old_repos_relpath,
                                 fb->old_revision,
@@ -4487,11 +4550,11 @@ close_file(void *file_baton,
       eb->notify_func(eb->notify_baton, notify, scratch_pool);
     }
 
-  /* We have one less referrer to the directory's bump information. */
-  SVN_ERR(maybe_release_dir_info(fb->bump_info));
-
   svn_pool_destroy(fb->pool); /* Destroy scratch_pool */
 
+  /* We have one less referrer to the directory */
+  SVN_ERR(maybe_release_dir_info(pdb));
+
   return SVN_NO_ERROR;
 }
 
@@ -4543,6 +4606,8 @@ close_edit(void *edit_baton,
                                                        *(eb->target_revision),
                                                        eb->skipped_trees,
                                                        eb->wcroot_iprops,
+                                                       eb->notify_func,
+                                                       eb->notify_baton,
                                                        eb->pool));
 
       if (*eb->target_basename != '\0')
@@ -5277,3 +5342,90 @@ svn_wc_add_repos_file4(svn_wc_context_t 
                                         cancel_func, cancel_baton,
                                         pool));
 }
+
+svn_error_t *
+svn_wc__complete_directory_add(svn_wc_context_t *wc_ctx,
+                               const char *local_abspath,
+                               apr_hash_t *new_original_props,
+                               const char *copyfrom_url,
+                               svn_revnum_t copyfrom_rev,
+                               apr_pool_t *scratch_pool)
+{
+  svn_wc__db_status_t status;
+  svn_kind_t kind;
+  const char *original_repos_relpath;
+  const char *original_root_url;
+  const char *original_uuid;
+  svn_boolean_t had_props;
+  svn_boolean_t props_mod;
+
+  svn_revnum_t original_revision;
+  svn_revnum_t changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
+
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL,
+                               &original_repos_relpath, &original_root_url,
+                               &original_uuid, &original_revision, NULL, NULL,
+                               NULL, NULL, NULL, NULL, &had_props, &props_mod,
+                               NULL, NULL, NULL,
+                               wc_ctx->db, local_abspath,
+                               scratch_pool, scratch_pool));
+
+  if (status != svn_wc__db_status_added
+      || kind != svn_kind_dir
+      || had_props
+      || props_mod
+      || !original_repos_relpath)
+    {
+      return svn_error_createf(
+                    SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                    _("'%s' is not an unmodified copied directory"),
+                    svn_dirent_local_style(local_abspath, scratch_pool));
+    }
+  if (original_revision != copyfrom_rev
+      || strcmp(copyfrom_url,
+                 svn_path_url_add_component2(original_root_url,
+                                             original_repos_relpath,
+                                             scratch_pool)))
+    {
+      return svn_error_createf(
+                    SVN_ERR_WC_COPYFROM_PATH_NOT_FOUND, NULL,
+                    _("Copyfrom '%s' doesn't match original location of '%s'"),
+                    copyfrom_url,
+                    svn_dirent_local_style(local_abspath, scratch_pool));
+    }
+
+  {
+    apr_array_header_t *regular_props;
+    apr_array_header_t *entry_props;
+
+    SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(new_original_props,
+                                                        scratch_pool),
+                                 &entry_props, NULL, &regular_props,
+                                 scratch_pool));
+
+    /* Put regular props back into a hash table. */
+    new_original_props = svn_prop_array_to_hash(regular_props, scratch_pool);
+
+    /* Get the change_* info from the entry props.  */
+    SVN_ERR(accumulate_last_change(&changed_rev,
+                                   &changed_date,
+                                   &changed_author,
+                                   entry_props, scratch_pool, scratch_pool));
+  }
+
+  return svn_error_trace(
+            svn_wc__db_op_copy_dir(wc_ctx->db, local_abspath,
+                                   new_original_props,
+                                   changed_rev, changed_date, changed_author,
+                                   original_repos_relpath, original_root_url,
+                                   original_uuid, original_revision,
+                                   NULL /* children */,
+                                   FALSE /* is_move */,
+                                   svn_depth_infinity,
+                                   NULL /* conflict */,
+                                   NULL /* work_items */,
+                                   scratch_pool));
+}

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/upgrade.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/upgrade.c Sat Feb 23 01:25:38 2013
@@ -1457,6 +1457,7 @@ svn_wc__upgrade_conflict_skel_from_raw(s
                                                       db, wri_abspath,
                                                       tc->reason,
                                                       tc->action,
+                                                      NULL,
                                                       scratch_pool,
                                                       scratch_pool));
 
@@ -1497,6 +1498,51 @@ svn_wc__upgrade_conflict_skel_from_raw(s
   return SVN_NO_ERROR;
 }
 
+/* Helper function to upgrade a single conflict from bump_to_30 */
+static svn_error_t *
+bump_30_upgrade_one_conflict(svn_wc__db_t *wc_db,
+                             const char *wcroot_abspath,
+                             svn_sqlite__stmt_t *stmt,
+                             svn_sqlite__db_t *sdb,
+                             apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt_store;
+  svn_stringbuf_t *skel_data;
+  svn_skel_t *conflict_data;
+  apr_int64_t wc_id = svn_sqlite__column_int64(stmt, 0);
+  const char *local_relpath = svn_sqlite__column_text(stmt, 1, NULL);
+  const char *conflict_old = svn_sqlite__column_text(stmt, 2, NULL);
+  const char *conflict_wrk = svn_sqlite__column_text(stmt, 3, NULL);
+  const char *conflict_new = svn_sqlite__column_text(stmt, 4, NULL);
+  const char *prop_reject = svn_sqlite__column_text(stmt, 5, NULL);
+  apr_size_t tree_conflict_size;
+  const char *tree_conflict_data = svn_sqlite__column_blob(stmt, 6,
+                                           &tree_conflict_size, NULL);
+
+  SVN_ERR(svn_wc__upgrade_conflict_skel_from_raw(&conflict_data,
+                                                 wc_db, wcroot_abspath,
+                                                 local_relpath,
+                                                 conflict_old,
+                                                 conflict_wrk,
+                                                 conflict_new,
+                                                 prop_reject,
+                                                 tree_conflict_data,
+                                                 tree_conflict_size,
+                                                 scratch_pool, scratch_pool));
+
+  SVN_ERR_ASSERT(conflict_data != NULL);
+
+  skel_data = svn_skel__unparse(conflict_data, scratch_pool);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt_store, sdb,
+                                    STMT_UPGRADE_30_SET_CONFLICT));
+  SVN_ERR(svn_sqlite__bindf(stmt_store, "isb", wc_id, local_relpath,
+                            skel_data->data, skel_data->len));
+  SVN_ERR(svn_sqlite__step_done(stmt_store));
+
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 bump_to_30(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
 {
@@ -1504,54 +1550,30 @@ bump_to_30(void *baton, svn_sqlite__db_t
   svn_boolean_t have_row;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_sqlite__stmt_t *stmt;
-  svn_sqlite__stmt_t *stmt_store;
   svn_wc__db_t *db; /* Read only temp db */
-  const char *wri_abspath = bb->wcroot_abspath;
 
-  SVN_ERR(svn_wc__db_open(&db, NULL, FALSE, FALSE,
+  SVN_ERR(svn_wc__db_open(&db, NULL, TRUE /* open_without_upgrade */, FALSE,
                           scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt_store, sdb,
-                                    STMT_UPGRADE_30_SET_CONFLICT));
-
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
   while (have_row)
     {
-      svn_stringbuf_t *skel_data;
-      svn_skel_t *conflict_data;
-      apr_int64_t wc_id = svn_sqlite__column_int64(stmt, 0);
-      const char *local_relpath = svn_sqlite__column_text(stmt, 1, NULL);
-      const char *conflict_old = svn_sqlite__column_text(stmt, 2, NULL);
-      const char *conflict_wrk = svn_sqlite__column_text(stmt, 3, NULL);
-      const char *conflict_new = svn_sqlite__column_text(stmt, 4, NULL);
-      const char *prop_reject = svn_sqlite__column_text(stmt, 5, NULL);
-      apr_size_t tree_conflict_size;
-      const char *tree_conflict_data = svn_sqlite__column_blob(stmt, 6,
-                                               &tree_conflict_size, NULL);
-
+      svn_error_t *err;
       svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_wc__upgrade_conflict_skel_from_raw(&conflict_data,
-                                                     db, wri_abspath,
-                                                     local_relpath,
-                                                     conflict_old,
-                                                     conflict_wrk,
-                                                     conflict_new,
-                                                     prop_reject,
-                                                     tree_conflict_data,
-                                                     tree_conflict_size,
-                                                     iterpool, iterpool));
-
-      SVN_ERR_ASSERT(conflict_data != NULL);
-
-      skel_data = svn_skel__unparse(conflict_data, iterpool);
-
-      SVN_ERR(svn_sqlite__bindf(stmt_store, "isb", wc_id, local_relpath,
-                                skel_data->data, skel_data->len));
-      SVN_ERR(svn_sqlite__step_done(stmt_store));
+      err = bump_30_upgrade_one_conflict(db, bb->wcroot_abspath, stmt, sdb,
+                                         iterpool);
+
+      if (err)
+        {
+          return svn_error_trace(
+                    svn_error_compose_create(
+                            err,
+                            svn_sqlite__reset(stmt)));
+        }
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
@@ -2134,17 +2156,21 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
   SVN_ERR(svn_wc__db_open(&db, NULL /* ### config */, TRUE, FALSE,
                           scratch_pool, scratch_pool));
 
+
   err = svn_wc__db_bump_format(&result_format, local_abspath, db,
                                scratch_pool);
   if (err)
     {
-      if (err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED) /* pre-1.7 WC */
+      if (err->apr_err != SVN_ERR_WC_UPGRADE_REQUIRED)
         {
-          svn_error_clear(err);
-          SVN_ERR(svn_wc__db_close(db));
+          return svn_error_trace(
+                    svn_error_compose_create(
+                            err,
+                            svn_wc__db_close(db)));
         }
-      else
-        return svn_error_trace(err);
+
+      svn_error_clear(err);
+      /* Pre 1.7: Fall through */
     }
   else
     {
@@ -2167,10 +2193,6 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
      'cleanup' with a new client will complete any outstanding
      upgrade. */
 
-  SVN_ERR(svn_wc__db_open(&db,
-                          NULL /* ### config */, TRUE, FALSE,
-                          scratch_pool, scratch_pool));
-
   SVN_ERR(svn_wc__read_entries_old(&entries, local_abspath,
                                    scratch_pool, scratch_pool));
 

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql Sat Feb 23 01:25:38 2013
@@ -29,7 +29,8 @@
 -- STMT_SELECT_NODE_INFO
 SELECT op_depth, repos_id, repos_path, presence, kind, revision, checksum,
   translated_size, changed_revision, changed_date, changed_author, depth,
-  symlink_target, last_mod_time, properties, moved_here, inherited_props
+  symlink_target, last_mod_time, properties, moved_here, inherited_props,
+  moved_to
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2
 ORDER BY op_depth DESC
@@ -96,12 +97,19 @@ FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
 
 -- STMT_SELECT_LOWEST_WORKING_NODE
-SELECT op_depth, presence, kind
+SELECT op_depth, presence, kind, moved_to
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3
 ORDER BY op_depth
 LIMIT 1
 
+-- STMT_SELECT_HIGHEST_WORKING_NODE
+SELECT op_depth
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth < ?3
+ORDER BY op_depth DESC
+LIMIT 1
+
 -- STMT_SELECT_ACTUAL_NODE
 SELECT changelist, properties, conflict_data
 FROM actual_node
@@ -239,6 +247,14 @@ WHERE wc_id = ?1
   AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
   AND op_depth = ?3
 
+-- STMT_SELECT_CHILDREN_OP_DEPTH
+SELECT local_relpath, kind
+FROM nodes
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = ?3
+ORDER BY local_relpath DESC
+
 -- STMT_COPY_NODE_MOVE
 INSERT OR REPLACE INTO nodes (
     wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
@@ -260,16 +276,24 @@ WHERE wc_id = ?1 AND local_relpath = ?2 
 
 -- STMT_SELECT_OP_DEPTH_CHILDREN
 SELECT local_relpath, kind FROM nodes
-WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = ?3
-  AND (?3 != 0 OR file_external is NULL)
+WHERE wc_id = ?1 
+  AND parent_relpath = ?2
+  AND op_depth = ?3
+  AND presence != MAP_BASE_DELETED
+  AND file_external is NULL
 
+/* Used by non-recursive revert to detect higher level children, and
+   actual-only rows that would be left orphans, if the revert
+   proceeded. */
 -- 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))
 UNION ALL
-SELECT 1 FROM ACTUAL_NODE
+SELECT 1 FROM ACTUAL_NODE a
 WHERE wc_id = ?1 AND parent_relpath = ?2
+  AND NOT EXISTS (SELECT 1 FROM nodes n
+                   WHERE wc_id = ?1 AND n.local_relpath = a.local_relpath)
 
 /* Delete the nodes shadowed by local_relpath. Not valid for the wc-root */
 -- STMT_DELETE_SHADOWED_RECURSIVE
@@ -279,6 +303,11 @@ WHERE wc_id = ?1
   AND (op_depth < ?3
        OR (op_depth = ?3 AND presence = MAP_BASE_DELETED))
 
+-- STMT_CLEAR_MOVED_TO_FROM_DEST
+UPDATE NODES SET moved_to = NULL
+WHERE wc_id = ?1
+  AND moved_to = ?2
+
 /* Get not-present descendants of a copied node. Not valid for the wc-root */
 -- STMT_SELECT_NOT_PRESENT_DESCENDANTS
 SELECT local_relpath FROM nodes
@@ -286,13 +315,21 @@ WHERE wc_id = ?1 AND op_depth = ?3
   AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
   AND presence = MAP_NOT_PRESENT
 
--- STMT_COMMIT_DESCENDANT_TO_BASE
-UPDATE NODES SET op_depth = 0, repos_id = ?4, repos_path = ?5, revision = ?6,
-  moved_here = NULL, moved_to = NULL, dav_cache = NULL,
-  presence = CASE presence WHEN MAP_NORMAL THEN MAP_NORMAL
-                           WHEN MAP_EXCLUDED THEN MAP_EXCLUDED
-                           ELSE MAP_NOT_PRESENT END
-WHERE wc_id = ?1 AND local_relpath = ?2 and op_depth = ?3
+-- STMT_COMMIT_DESCENDANTS_TO_BASE
+UPDATE NODES SET op_depth = 0,
+                 repos_id = ?4,
+                 repos_path = ?5 || SUBSTR(local_relpath, LENGTH(?2)+1),
+                 revision = ?6,
+                 dav_cache = NULL,
+                 moved_here = NULL,
+                 presence = CASE presence
+                              WHEN MAP_NORMAL THEN MAP_NORMAL
+                              WHEN MAP_EXCLUDED THEN MAP_EXCLUDED
+                              ELSE MAP_NOT_PRESENT
+                            END
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = ?3
 
 -- STMT_SELECT_NODE_CHILDREN
 /* Return all paths that are children of the directory (?1, ?2) in any
@@ -398,7 +435,39 @@ SELECT moved_here, presence, repos_path,
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth >= ?3
 ORDER BY op_depth
-                  
+
+-- STMT_SELECT_MOVED_BACK
+SELECT u.local_relpath,
+       u.presence, u.repos_id, u.repos_path, u.revision,
+       l.presence, l.repos_id, l.repos_path, l.revision,
+       u.moved_here, u.moved_to
+FROM nodes u
+LEFT OUTER JOIN nodes l ON l.wc_id = ?1
+                       AND l.local_relpath = u.local_relpath
+                       AND l.op_depth = ?3
+WHERE u.wc_id = ?1
+  AND u.local_relpath = ?2
+  AND u.op_depth = ?4
+UNION ALL
+SELECT u.local_relpath,
+       u.presence, u.repos_id, u.repos_path, u.revision,
+       l.presence, l.repos_id, l.repos_path, l.revision,
+       u.moved_here, NULL
+FROM nodes u
+LEFT OUTER JOIN nodes l ON l.wc_id=?1
+                       AND l.local_relpath=u.local_relpath
+                       AND l.op_depth=?3
+WHERE u.wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(u.local_relpath, ?2)
+  AND u.op_depth = ?4
+
+-- STMT_DELETE_MOVED_BACK
+DELETE FROM nodes
+WHERE wc_id = ?1
+  AND (local_relpath = ?2
+       OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+  AND op_depth = ?3
+
 -- STMT_DELETE_LOCK
 DELETE FROM lock
 WHERE repos_id = ?1 AND repos_relpath = ?2
@@ -1307,6 +1376,30 @@ ORDER BY local_relpath
 -- STMT_FINALIZE_DELETE
 DROP TABLE IF EXISTS delete_list
 
+-- STMT_CREATE_UPDATE_MOVE_LIST
+DROP TABLE IF EXISTS update_move_list;
+CREATE TEMPORARY TABLE update_move_list (
+/* ### we should put the wc_id in here in case a move update spans multiple
+   ### working copies. queries, etc will need to be adjusted.  */
+  local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE,
+  action INTEGER NOT NULL,
+  kind  INTEGER NOT NULL,
+  content_state INTEGER NOT NULL,
+  prop_state  INTEGER NOT NULL
+  )
+
+-- STMT_INSERT_UPDATE_MOVE_LIST
+INSERT INTO update_move_list(local_relpath, action, kind, content_state,
+  prop_state)
+VALUES (?1, ?2, ?3, ?4, ?5)
+
+-- STMT_SELECT_UPDATE_MOVE_LIST
+SELECT local_relpath, action, kind, content_state, prop_state
+FROM update_move_list
+ORDER BY local_relpath
+
+-- STMT_FINALIZE_UPDATE_MOVE
+DROP TABLE IF EXISTS update_move_list
 
 /* ------------------------------------------------------------------------- */
 
@@ -1349,73 +1442,15 @@ WHERE wc_id = ?1
   AND properties IS NOT NULL
 LIMIT 1
 
-/* Determine if there is some switched subtree in just SQL. This looks easy,
-   but it really isn't, because we don't have a simple (and optimizable)
-   path join operation in SQL.
-
-   To work around that we have 4 different cases:
-      * Check on a node that is neither wcroot nor repos root
-      * Check on a node that is repos_root, but not wcroot.
-      * Check on a node that is wcroot, but not repos root.
-      * Check on a node that is both wcroot and repos root.
-
-   To make things easier, our testsuite is usually in that last category,
-   while normal working copies are almost always in one of the others.
-*/
 -- STMT_HAS_SWITCHED
-SELECT o.repos_path || '/' || SUBSTR(s.local_relpath, LENGTH(?2)+2) AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
-LIMIT 1
-
--- STMT_HAS_SWITCHED_REPOS_ROOT
-SELECT SUBSTR(s.local_relpath, LENGTH(?2)+2) AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
-LIMIT 1
-
--- STMT_HAS_SWITCHED_WCROOT
-SELECT o.repos_path || '/' || s.local_relpath AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND s.local_relpath != ''
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
-LIMIT 1
-
--- STMT_HAS_SWITCHED_WCROOT_REPOS_ROOT
-SELECT s.local_relpath AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND s.local_relpath != ''
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
+SELECT 1
+FROM nodes
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = 0
+  AND file_external IS NULL
+  AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+  AND repos_path IS NOT RELPATH_SKIP_JOIN(?2, ?3, local_relpath)
 LIMIT 1
 
 -- STMT_SELECT_BASE_FILES_RECURSIVE
@@ -1441,6 +1476,12 @@ WHERE wc_id = ?1 AND local_relpath = ?2 
 UPDATE nodes SET moved_to = NULL
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
 
+-- STMT_CLEAR_MOVED_HERE_RECURSIVE
+UPDATE nodes SET moved_here = NULL
+WHERE wc_id = ?1
+ AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+ AND op_depth = ?3
+
 /* This statement returns pairs of move-roots below the path ?2 in WC_ID ?1.
  * Each row returns a moved-here path (always a child of ?2) in the first
  * column, and its matching moved-away (deleted) path in the second column. */
@@ -1463,23 +1504,92 @@ WHERE wc_id = ?1
  * where the source of the move is within the subtree rooted at path ?2, and
  * the destination of the move is outside the subtree rooted at path ?2. */
 -- STMT_SELECT_MOVED_PAIR2
-SELECT local_relpath, moved_to FROM nodes_current
+SELECT local_relpath, moved_to, op_depth FROM nodes
 WHERE wc_id = ?1
-  AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
   AND moved_to IS NOT NULL
   AND NOT IS_STRICT_DESCENDANT_OF(moved_to, ?2)
+  AND op_depth >= (SELECT MAX(op_depth) FROM nodes o
+                    WHERE o.wc_id = ?1
+                      AND o.local_relpath = ?2)
 
 -- STMT_SELECT_MOVED_PAIR3
-SELECT local_relpath, moved_to, op_depth FROM nodes
+SELECT local_relpath, moved_to, op_depth, kind FROM nodes
 WHERE wc_id = ?1
   AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
   AND op_depth > ?3
   AND moved_to IS NOT NULL
 
+-- STMT_SELECT_MOVED_OUTSIDE
+SELECT local_relpath FROM nodes
+WHERE wc_id = ?1
+  AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+  AND op_depth >= ?3
+  AND moved_to IS NOT NULL
+  AND NOT IS_STRICT_DESCENDANT_OF(moved_to, ?2)
+
+-- STMT_SELECT_OP_DEPTH_MOVED_PAIR
+SELECT n.local_relpath, n.moved_to,
+       (SELECT o.repos_path FROM nodes AS o
+        WHERE o.wc_id = n.wc_id
+          AND o.local_relpath = n.local_relpath
+          AND o.op_depth < ?3 ORDER BY o.op_depth DESC LIMIT 1)
+FROM nodes AS n
+WHERE n.wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
+  AND n.op_depth = ?3
+  AND n.moved_to IS NOT NULL
+
+-- STMT_SELECT_MOVED_DESCENDANTS
+SELECT n.local_relpath, h.moved_to
+FROM nodes n, nodes h
+WHERE n.wc_id = ?1
+  AND h.wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
+  AND h.local_relpath = n.local_relpath
+  AND n.op_depth = ?3
+  AND h.op_depth = (SELECT MIN(o.op_depth)
+                    FROM nodes o
+                    WHERE o.wc_id = ?1
+                      AND o.local_relpath = n.local_relpath
+                      AND o.op_depth > ?3)
+  AND h.moved_to IS NOT NULL
+
+-- STMT_COMMIT_UPDATE_ORIGIN
+/* Note that the only reason this SUBSTR() trick is valid is that you
+   can move neither the working copy nor the repository root.
+
+   SUBSTR(local_relpath, LENGTH(?2)+1) includes the '/' of the path */
+UPDATE nodes SET repos_id = ?4,
+                 repos_path = ?5 || SUBSTR(local_relpath, LENGTH(?2)+1),
+                 revision = ?6
+WHERE wc_id = ?1
+  AND (local_relpath = ?2
+       OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+  AND op_depth = ?3
+
 -- STMT_HAS_LAYER_BETWEEN
 SELECT 1 FROM NODES
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3 AND op_depth < ?4
 
+-- STMT_SELECT_REPOS_PATH_REVISION
+SELECT local_relpath, repos_path, revision FROM nodes
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = 0
+ORDER BY local_relpath
+
+-- STMT_SELECT_HAS_NON_FILE_CHILDREN
+SELECT 1 FROM nodes
+WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0 AND kind != MAP_FILE
+
+-- STMT_SELECT_HAS_GRANDCHILDREN
+SELECT 1 FROM nodes
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(parent_relpath, ?2)
+  AND op_depth = 0
+  AND file_external IS NULL
+
 /* ------------------------------------------------------------------------- */
 
 /* Queries for verification. */

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc.h Sat Feb 23 01:25:38 2013
@@ -615,21 +615,15 @@ svn_wc__internal_get_origin(svn_boolean_
 
 /* Internal version of svn_wc__node_get_repos_info() */
 svn_error_t *
-svn_wc__internal_get_repos_info(const char **repos_root_url,
+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);
 
-/* Internal version of svn_wc__node_get_repos_relpath() */
-svn_error_t *
-svn_wc__internal_get_repos_relpath(const char **repos_relpath,
-                                   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



Mime
View raw message