@@ -85,14 +85,44 @@ static svn_error_t *
do_close (svn_wc_adm_access_t *adm_access, svn_boolean_t preserve_lock);
+/* Maybe upgrade the working copy directory represented by ADM_ACCESS
+ to the latest 'SVN_WC__VERSION'. This may involve renaming some
+ administrative files, therefore ADM_ACCESS must contain a write
+ lock. Use POOL for all temporary allocation.
+
+ Not all upgrade paths are necessarily supported. For example,
+ upgrading a version 1 working copy results in an error.
+
+ Sometimes the format file can contain "0" while the administrative
+ directory is being constructed; calling this on a format 0 working
+ copy has no effect and returns no error. */
static svn_error_t *
-upgrade_format (svn_wc_adm_access_t *adm_access, apr_pool_t *pool)
+maybe_upgrade_format (svn_wc_adm_access_t *adm_access, apr_pool_t *pool)
{
- /* ### We'll write the upgrade code later. For now, punt. */
- return svn_error_createf
- (SVN_ERR_WC_CORRUPT, NULL,
- "TODO: '%s' needs a format upgrade, but we haven't written the code yet",
- adm_access->path);
+ if (adm_access->wc_format == 1)
+ {
+ return svn_error_createf
+ (SVN_ERR_WC_FORMAT_UPGRADE, NULL,
+ "working copy format 1 is too old to upgrade, in '%s';\n"
+ "please check out your working copy again",
+ adm_access->path);
+ }
+ else if (adm_access->wc_format == 2)
+ {
+ const char *path = svn_wc__adm_path (adm_access->path, FALSE, pool,
+ SVN_WC__ADM_FORMAT, NULL);
+
+ SVN_ERR (svn_io_write_version_file (path, SVN_WC__VERSION, pool));
+ adm_access->wc_format = SVN_WC__VERSION;
+ }
+ else if (adm_access->wc_format > SVN_WC__VERSION)
+ {
+ return svn_error_createf
+ (SVN_ERR_WC_FORMAT_UPGRADE, NULL,
+ "this client is much too old to work with working copy '%s';\n"
+ "please get a newer Subversion client",
+ adm_access->path);
+ }
return SVN_NO_ERROR;
}
@@ -100,7 +130,12 @@ upgrade_format (svn_wc_adm_access_t *adm_access, apr_pool_t *pool)
/* Create a physical lock file in the admin directory for ADM_ACCESS. Wait
up to WAIT_FOR seconds if the lock already exists retrying every
- second. */
+ second.
+
+ Note: most callers of this function determine the wc_format for the
+ lock soon afterwards. We recommend calling maybe_upgrade_format()
+ as soon as you have the wc_format for a lock, since that's a good
+ opportunity to drag old working directories into the modern era. */
static svn_error_t *
create_lock (svn_wc_adm_access_t *adm_access, int wait_for, apr_pool_t *pool)
{
@@ -124,17 +159,7 @@ create_lock (svn_wc_adm_access_t *adm_access, int wait_for, apr_pool_t *pool)
return err;
}
else
- {
- /* We have a write lock. If the working copy has an old
- format, this is the time to upgrade it. */
- if ((adm_access->wc_format > 0)
- && (adm_access->wc_format < SVN_WC__VERSION))
- {
- SVN_ERR (upgrade_format (adm_access, pool));
- }
-
- return SVN_NO_ERROR;
- }
+ return SVN_NO_ERROR;
}
return svn_error_createf (SVN_ERR_WC_LOCKED, NULL,
@@ -279,8 +304,11 @@ svn_wc__adm_steal_write_lock (svn_wc_adm_access_t **adm_access,
apr_hash_set (lock->set, lock->path, APR_HASH_KEY_STRING, lock);
}
+ /* We have a write lock. If the working copy has an old
+ format, this is the time to upgrade it. */
SVN_ERR (svn_wc_check_wc (path, &lock->wc_format, pool));
-
+ SVN_ERR (maybe_upgrade_format (lock, pool));
+
lock->lock_exists = TRUE;
*adm_access = lock;
return SVN_NO_ERROR;
@@ -350,8 +378,12 @@ do_open (svn_wc_adm_access_t **adm_access,
{
lock = adm_access_alloc (svn_wc__adm_access_unlocked, path, pool);
}
+
if (! under_construction)
- lock->wc_format = wc_format;
+ {
+ lock->wc_format = wc_format;
+ SVN_ERR (maybe_upgrade_format (lock, pool));
+ }
if (tree_lock)
{