Author: philip
Date: Wed Sep  8 18:34:20 2010
New Revision: 995183

URL: http://svn.apache.org/viewvc?rev=995183&view=rev
Log:
Make interrupting the upgrade of a pre-1.7 working copy leave the
working copy in a working state.

* subversion/libsvn_wc/wc.h
  (svn_wc__wipe_postupgrade): New.

* subversion/libsvn_wc/upgrade.c
  (): Include workqueue.h.
  (svn_wc__wipe_postupgrade): New.
  (upgrade_to_wcng): Put temporary db in .svn/tmp, don't remove old metadata.
  (svn_wc_upgrade): Add wq items and run the wq, close and reopen
   db handle rather than droping the root.

* subversion/libsvn_wc/workqueue.h
  (svn_wc__wq_build_postupgrade): New.

* subversion/libsvn_wc/workqueue.c
  (OP_POSTUPGRADE, run_postupgrade, svn_wc__wq_build_postupgrade): New.
  (dispatch_table): Add OP_POSTUPGRADE.

Modified:
    subversion/trunk/subversion/libsvn_wc/upgrade.c
    subversion/trunk/subversion/libsvn_wc/wc.h
    subversion/trunk/subversion/libsvn_wc/workqueue.c
    subversion/trunk/subversion/libsvn_wc/workqueue.h

Modified: subversion/trunk/subversion/libsvn_wc/upgrade.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/upgrade.c?rev=995183&r1=995182&r2=995183&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/trunk/subversion/libsvn_wc/upgrade.c Wed Sep  8 18:34:20 2010
@@ -35,6 +35,7 @@
 #include "wc_db.h"
 #include "tree_conflicts.h"
 #include "wc-queries.h"  /* for STMT_*  */
+#include "workqueue.h"
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
@@ -495,6 +496,42 @@ wipe_obsolete_files(const char *wcroot_a
                     TRUE, scratch_pool));
 }
 
+svn_error_t *
+svn_wc__wipe_postupgrade(const char *dir_abspath,
+                         svn_boolean_t whole_admin,
+                         svn_cancel_func_t cancel_func,
+                         void *cancel_baton,
+                         apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_array_header_t *subdirs;
+  int i;
+
+  if (cancel_func)
+    SVN_ERR((*cancel_func)(cancel_baton));
+
+  SVN_ERR(get_versioned_subdirs(&subdirs, dir_abspath, scratch_pool, 
iterpool));
+  for (i = 0; i < subdirs->nelts; ++i)
+    {
+      const char *child_abspath = APR_ARRAY_IDX(subdirs, i, const char *);
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_wc__wipe_postupgrade(child_abspath, TRUE,
+                                       cancel_func, cancel_baton, iterpool));
+    }
+
+  /* ### Should we really be ignoring errors here? */
+  if (whole_admin)
+    svn_error_clear(svn_io_remove_dir2(svn_wc__adm_child(dir_abspath, "",
+                                                         iterpool),
+                                       TRUE, NULL, NULL, iterpool));
+  else
+    wipe_obsolete_files(dir_abspath, scratch_pool);
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
 
 /* Ensure that ENTRY has its REPOS and UUID fields set. These will be
    used to establish the REPOSITORY row in the new database, and then
@@ -1252,11 +1289,11 @@ upgrade_to_wcng(svn_wc__db_t *db,
     {
       const char *root_adm_abspath;
 
-      /* In root wc construst path to temporary root wc/.svn/wcng/.svn
+      /* In root wc construst path to temporary root wc/.svn/tmp/wcng/.svn */
 
-         ### This should really be in tmp so that 1.6 can cleanup if
-             interrupted, i.e. wc/.svn/tmp/wcng/.svn */
-      data->root_abspath = svn_wc__adm_child(dir_abspath, "wcng", result_pool);
+      data->root_abspath = svn_dirent_join(svn_wc__adm_child(dir_abspath, 
"tmp",
+                                                             scratch_pool),
+                                           "wcng", result_pool);
       root_adm_abspath = svn_wc__adm_child(data->root_abspath, "",
                                            scratch_pool);
       SVN_ERR(svn_wc__ensure_directory(root_adm_abspath, scratch_pool));
@@ -1323,20 +1360,6 @@ upgrade_to_wcng(svn_wc__db_t *db,
   /* All done. DB should finalize the upgrade process now.  */
   SVN_ERR(svn_wc__db_upgrade_finish(dir_abspath, data->sdb, scratch_pool));
 
-  /* Zap all the obsolete files. This removes the old-style lock file.
-     In single-db we should postpone this until we have processed all
-     entries files into the single-db, otherwise an interrupted
-     upgrade is nasty.  Perhaps add a wq item?  If we do postpone then
-     perhaps we should still remove the lock otherwise the user has to
-     use 1.6 to cleanup. */
-  wipe_obsolete_files(dir_abspath, scratch_pool);
-
-  /* Remove the admin dir in subdirectories of the root. */
-  if (!svn_dirent_is_ancestor(dir_abspath, data->root_abspath))
-    svn_error_clear(svn_io_remove_dir2(svn_wc__adm_child(dir_abspath, NULL,
-                                                         scratch_pool),
-                                       FALSE, NULL, NULL, scratch_pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -1599,12 +1622,8 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
 {
   svn_wc__db_t *db;
   struct upgrade_data_t data = { NULL };
-
-  /* We need a DB that does not attempt an auto-upgrade, nor require
-     running a stale work queue. We'll handle everything manually.  */
-  SVN_ERR(svn_wc__db_open(&db, svn_wc__db_openmode_readwrite,
-                          NULL /* ### config */, FALSE, FALSE,
-                          scratch_pool, scratch_pool));
+  svn_skel_t *work_item, *work_items = NULL;
+  const char *pristine_from, *pristine_to, *db_from, *db_to;
 
   if (!is_old_wcroot(local_abspath, scratch_pool))
     return svn_error_createf(
@@ -1612,7 +1631,20 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
       _("Cannot upgrade '%s' as it is not a pre-1.7 working copy root"),
       svn_dirent_local_style(local_abspath, scratch_pool));
 
-  /* Upgrade this directory and/or its subdirectories.  */
+  /* Given a pre-wcng root some/wc we create a temporary wcng in
+     some/wc/.svn/tmp/wcng/wc.db and copy the metadata from one to the
+     other, then the temporary wc.db file gets moved into the original
+     root.  Until the wc.db file is moved the original working copy
+     remains a pre-wcng and 'cleanup' with an old client will remove
+     the partial upgrade.  Moving the wc.db file creates a wcng, and
+     'cleanup' with a new client will complete any outstanding
+     upgrade. */
+
+  SVN_ERR(svn_wc__db_open(&db, svn_wc__db_openmode_readwrite,
+                          NULL /* ### config */, FALSE, FALSE,
+                          scratch_pool, scratch_pool));
+
+  /* Upgrade the pre-wcng into a wcng in a temporary location. */
   SVN_ERR(upgrade_working_copy(db, local_abspath,
                                repos_info_func, repos_info_baton,
                                apr_hash_make(scratch_pool), &data,
@@ -1620,32 +1652,42 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                                notify_func, notify_baton,
                                scratch_pool));
 
+  /* A workqueue item to move the pristine dir into place */
+  pristine_from = svn_wc__adm_child(data.root_abspath, 
PRISTINE_STORAGE_RELPATH,
+                                    scratch_pool);
+  pristine_to = svn_wc__adm_child(local_abspath, PRISTINE_STORAGE_RELPATH,
+                                  scratch_pool);
+  SVN_ERR(svn_wc__wq_build_file_move(&work_item, db,
+                                     pristine_from, pristine_to,
+                                     scratch_pool, scratch_pool));
+  work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+
+  /* A workqueue item to remove pre-wcng metadata */
+  SVN_ERR(svn_wc__wq_build_postupgrade(&work_item, scratch_pool));
+  work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+  SVN_ERR(svn_wc__db_wq_add(db, data.root_abspath, work_items, scratch_pool));
+
   SVN_ERR(svn_wc__db_wclock_release(db, data.root_abspath, scratch_pool));
-  SVN_ERR(svn_wc__db_drop_root(db, data.root_abspath, scratch_pool));
   SVN_ERR(svn_sqlite__close(data.sdb));
-  {
-    const char *pristine_from = svn_wc__adm_child(data.root_abspath,
-                                                  PRISTINE_STORAGE_RELPATH,
-                                                  scratch_pool);
-    const char *pristine_to = svn_wc__adm_child(local_abspath,
-                                                PRISTINE_STORAGE_RELPATH,
-                                                scratch_pool);
-    SVN_ERR(svn_io_file_rename(pristine_from, pristine_to, scratch_pool));
-  }
-  {
-    const char *db_from = svn_wc__adm_child(data.root_abspath, SDB_FILE,
-                                            scratch_pool);
-    const char *db_to = svn_wc__adm_child(local_abspath, SDB_FILE,
-                                          scratch_pool);
-    SVN_ERR(svn_io_file_rename(db_from, db_to, scratch_pool));
-  }
-  {
-    SVN_ERR(svn_io_remove_dir2(data.root_abspath, FALSE, NULL, NULL,
-                               scratch_pool));
-  }
+  SVN_ERR(svn_wc__db_close(db));
+
+  /* Renaming the db file is what makes the pre-wcng into a wcng */
+  db_from = svn_wc__adm_child(data.root_abspath, SDB_FILE, scratch_pool);
+  db_to = svn_wc__adm_child(local_abspath, SDB_FILE, scratch_pool);
+  SVN_ERR(svn_io_file_rename(db_from, db_to, scratch_pool));
 
+  /* Now we have a working wcng, tidy up the droppings */
+  SVN_ERR(svn_wc__db_open(&db, svn_wc__db_openmode_readwrite,
+                          NULL /* ### config */, FALSE, FALSE,
+                          scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                         scratch_pool));
   SVN_ERR(svn_wc__db_close(db));
 
+  /* Should we have the workqueue remove this empty dir? */
+  SVN_ERR(svn_io_remove_dir2(data.root_abspath, FALSE, NULL, NULL,
+                             scratch_pool));
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_wc/wc.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc.h?rev=995183&r1=995182&r2=995183&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc.h Wed Sep  8 18:34:20 2010
@@ -649,6 +649,13 @@ svn_wc__upgrade_sdb(int *result_format,
                     apr_pool_t *scratch_pool);
 
 
+svn_error_t *
+svn_wc__wipe_postupgrade(const char *dir_abspath,
+                         svn_boolean_t whole_admin,
+                         svn_cancel_func_t cancel_func,
+                         void *cancel_baton,
+                         apr_pool_t *scratch_pool);
+
 /* Check whether a node is a working copy root or switched.
  *
  * If LOCAL_ABSPATH is the root of a working copy, set *WC_ROOT to TRUE,

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=995183&r1=995182&r2=995183&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Wed Sep  8 18:34:20 2010
@@ -59,6 +59,7 @@
 #define OP_TMP_SET_TEXT_CONFLICT_MARKERS "tmp-set-text-conflict-markers"
 #define OP_TMP_SET_PROPERTY_CONFLICT_MARKER "tmp-set-property-conflict-marker"
 #define OP_PRISTINE_GET_TRANSLATED "pristine-get-translated"
+#define OP_POSTUPGRADE "postupgrade"
 
 /* For work queue debugging. Generates output about its operation.  */
 /* #define DEBUG_WORK_QUEUE */
@@ -1610,6 +1611,34 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
 }
 
 /* ------------------------------------------------------------------------ */
+/* OP_POSTUPGRADE  */
+
+static svn_error_t *
+run_postupgrade(svn_wc__db_t *db,
+                const svn_skel_t *work_item,
+                const char *wri_abspath,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
+                apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_wc__wipe_postupgrade(wri_abspath, FALSE,
+                                   cancel_func, cancel_baton, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__wq_build_postupgrade(svn_skel_t **work_item,
+                             apr_pool_t *result_pool)
+{
+  *work_item = svn_skel__make_empty_list(result_pool);
+
+  svn_skel__prepend_str(OP_POSTUPGRADE, *work_item, result_pool);
+
+  return SVN_NO_ERROR;
+}
+
+/* ------------------------------------------------------------------------ */
 
 /* OP_FILE_INSTALL */
 
@@ -2393,6 +2422,7 @@ static const struct work_item_dispatch d
   { OP_TMP_SET_TEXT_CONFLICT_MARKERS, run_set_text_conflict_markers },
   { OP_TMP_SET_PROPERTY_CONFLICT_MARKER, run_set_property_conflict_marker },
   { OP_PRISTINE_GET_TRANSLATED, run_pristine_get_translated },
+  { OP_POSTUPGRADE, run_postupgrade },
 
 #ifndef SVN_WC__SINGLE_DB
   { OP_KILLME, run_killme },

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.h?rev=995183&r1=995182&r2=995183&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.h Wed Sep  8 18:34:20 2010
@@ -301,6 +301,10 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
                           svn_boolean_t no_unlock,
                           apr_pool_t *scratch_pool);
 
+svn_error_t *
+svn_wc__wq_build_postupgrade(svn_skel_t **work_item,
+                             apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */


Reply via email to