Julian Foad <[email protected]> writes:
> Issue #4889 "per-WC config" is the subject of Johan's new dev@ post
> "Pristines-on-demand=enabled == format 32?". We already concurred that
> it's wise to decouple "pristines-on-demand mode is enabled in this WC"
> from "the WC format is (at least) 32 so can support that mode".
> <https://subversion.apache.org/issue/4889>. This may be considered
> higher priority than fixing the remaining tests.
I have been thinking about this recently, and here is a patch with the
first-cut implementation that persists the pristines-on-demand setting
in a working copy. Unfortunately, I am getting a bit swamped with other
things to complete the work on it, but perhaps it could be useful as a
building block for the full implementation.
The patch currently allows doing an `svn checkout --store-pristines=no`,
which is going to create a working copy that doesn't store the pristine
copies of the files and fetches them on demand. The setting is persisted
in wc.db.
The patch doesn't include the following:
1) An update for the tests and the test suite to run the tests in both modes.
Personally, I think that we should update the test runner so that it would
execute the tests for both pristine modes by default, without requiring any
specific switches. Because otherwise, there is a chance that one of the
equally supported core configurations may receive far less attention
during the development and test runs.
2) An update for `svn info` to display the value of the new setting.
3) An ability to take the --store-pristines value from a user config, perhaps
on a per-URL basis.
While working on the patch, I have stumbled across a couple of issues:
A) `svn upgrade` without arguments fails for a working copy with latest format
$ svn checkout --compatible-version=1.15 wc
$ svn upgrade wc
$ svn: E155021: Working copy '…' is already at version 1.15 (format 32)
and cannot be downgraded to version 1.8 (format 31)
I haven't given it a lot of thought, but we might want to handle this case
without an error or even think about making `svn upgrade` by default upgrade
to the latest available version instead of the minimum supported (similar to
`svnadmin upgrade`).
B) Shelving and pristines-on-demand
It seems that both v2 and v3 shelving implementations are currently not
updated to support pristines-on-demand working copies.
C) Bumping the related API
This part originates from B). For example, v3 shelving uses the libsvn_wc
APIs, such as svn_wc_revert6(). If the working copy is created without the
pristine contents, those calls are going to fail with an error saying that
there is no text-base for the corresponding path. This is a tricky error to
understand, and the failure itself is unpredictable, because it depends on
whether any of the previous API calls have fetched the missing text-bases.
So if we think about v3 shelving as an example of the libsvn_wc API user,
other existing third-party users of the API could face the same problem.
Perhaps, we could bump the APIs that currently rely on the text-bases to
always be available. And we could then make their deprecated versions
fail (predictably) for working copies that don't store pristine contents.
Thanks,
Evgeny Kotkov
Index: subversion/include/private/svn_wc_private.h
===================================================================
--- subversion/include/private/svn_wc_private.h (revision 1899956)
+++ subversion/include/private/svn_wc_private.h (working copy)
@@ -2231,9 +2231,11 @@ const svn_version_t *
svn_wc__min_supported_format_version(void);
/**
- * Set @a format to the format of the nearest parent working copy root of
- * @a local_abspath in @a wc_ctx, or to the oldest format of any root stored
- * there. If @a wc_ctx is empty, return the library's default format.
+ * Set @a *format_p and @a *store_pristines_p to the settings of the
+ * nearest parent working copy root of @a local_abspath in @a wc_ctx,
+ * or to settings of any root stored there, preferring the one with
+ * the oldest format. If @a wc_ctx is empty, return the library's
+ * default settings.
*
* Use @a scratch_pool for temporary allocations.
*
@@ -2240,16 +2242,18 @@ svn_wc__min_supported_format_version(void);
* @since New in 1.15.
*/
svn_error_t *
-svn_wc__format_from_context(int *format,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
+svn_wc__settings_from_context(int *format_p,
+ svn_boolean_t *store_pristines_p,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool);
/**
* Ensure that an administrative area exists for @a local_abspath, so that @a
* local_abspath is a working copy subdir with schema version @a target_format
- * based on @a url at @a revision, with depth @a depth, and with repository
UUID
- * @a repos_uuid and repository root URL @a repos_root_url.
+ * based on @a url at @a revision, with depth @a depth, with repository UUID
+ * @a repos_uuid and repository root URL @a repos_root_url, and with the
+ * @a store_pristines setting value.
*
* @a depth must be a definite depth, it cannot be #svn_depth_unknown.
* @a repos_uuid and @a repos_root_url MUST NOT be @c NULL, and
@@ -2280,11 +2284,13 @@ svn_wc__ensure_adm(svn_wc_context_t *wc_ctx,
const char *repos_uuid,
svn_revnum_t revision,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool);
/**
- * Upgrade the working copy at @a local_abspath to the metadata
- * storage format indicated by @a target_format. @a local_abspath
+ * Upgrade the working copy at @a local_abspath to the metadata storage
+ * format indicated by @a target_format. Use the @a store_pristines
+ * settings value for the upgraded working copy. @a local_abspath
* should be an absolute path to the root of the working copy.
*
* If @a cancel_func is non-NULL, invoke it with @a cancel_baton at
@@ -2306,6 +2312,7 @@ svn_error_t *
svn_wc__upgrade(svn_wc_context_t *wc_ctx,
const char *local_abspath,
int target_format,
+ svn_boolean_t store_pristines,
svn_wc_upgrade_get_repos_info_t repos_info_func,
void *repos_info_baton,
svn_cancel_func_t cancel_func,
@@ -2341,6 +2348,15 @@ svn_wc__textbase_sync(svn_wc_context_t *wc_ctx,
void *cancel_baton,
apr_pool_t *scratch_pool);
+/* Return the working copy settings *FORMAT_P and *STORE_PRISTINES_P for
+ LOCAL_ABSPATH in WC_CTX. */
+svn_error_t *
+svn_wc__get_settings(int *format_p,
+ svn_boolean_t *store_pristines_p,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h (revision 1899956)
+++ subversion/include/svn_client.h (working copy)
@@ -1245,6 +1245,11 @@ svn_client_args_to_target_array(apr_array_header_t
* @c NULL means the library's version.
* See svn_client_default_wc_version(),
* svn_client_get_wc_formats_supported().
+ * @param[in] store_pristines If #svn_tristate_true, the pristine contents of
+ * all files in the working copy will be stored on disk. <br>
+ * If #svn_tristate_false, the pristine contents will be fetched
+ * on-demand when required by the operation. <br>
+ * If #svn_tristate_unknown, the default setting will be used.
* @param[in] ctx The standard client context, used for authentication and
* notification.
* @param[in] pool Used for any temporary allocation.
@@ -1274,6 +1279,7 @@ svn_client_checkout4(svn_revnum_t *result_rev,
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
const svn_version_t *wc_format_version,
+ svn_tristate_t store_pristines,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
Index: subversion/include/svn_error_codes.h
===================================================================
--- subversion/include/svn_error_codes.h (revision 1899956)
+++ subversion/include/svn_error_codes.h (working copy)
@@ -576,6 +576,11 @@ SVN_ERROR_START
SVN_ERR_WC_CATEGORY_START + 41,
"Duplicate targets in svn:externals property")
+ /** @since New in 1.15 */
+ SVN_ERRDEF(SVN_ERR_WC_INCOMPATIBLE_SETTINGS,
+ SVN_ERR_WC_CATEGORY_START + 42,
+ "Incompatible working copy settings")
+
/* fs errors */
SVN_ERRDEF(SVN_ERR_FS_GENERAL,
Index: subversion/libsvn_client/checkout.c
===================================================================
--- subversion/libsvn_client/checkout.c (revision 1899956)
+++ subversion/libsvn_client/checkout.c (working copy)
@@ -38,8 +38,10 @@
#include "svn_io.h"
#include "svn_opt.h"
#include "svn_time.h"
+#include "svn_version.h"
#include "client.h"
+#include "private/svn_subr_private.h"
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
@@ -52,6 +54,7 @@ initialize_area(int target_format,
const char *local_abspath,
const svn_client__pathrev_t *pathrev,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -62,7 +65,7 @@ initialize_area(int target_format,
SVN_ERR(svn_wc__ensure_adm(ctx->wc_ctx,
target_format, local_abspath, pathrev->url,
pathrev->repos_root_url, pathrev->repos_uuid,
- pathrev->rev, depth, pool));
+ pathrev->rev, depth, store_pristines, pool));
return SVN_NO_ERROR;
}
@@ -78,11 +81,13 @@ svn_client__checkout_internal(svn_revnum_t *result
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
const svn_version_t *wc_format_version,
+ svn_tristate_t store_pristines,
svn_ra_session_t *ra_session,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
int target_format;
+ svn_boolean_t target_store_pristines;
svn_node_kind_t kind;
svn_client__pathrev_t *pathrev;
svn_opt_revision_t resolved_rev = { svn_opt_revision_number };
@@ -98,15 +103,28 @@ svn_client__checkout_internal(svn_revnum_t *result
&& (revision->kind != svn_opt_revision_head))
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
- /* Here the default for wc_format_version is determined from WC context,
- * rather than the library's default version. */
- if (wc_format_version)
- SVN_ERR(svn_wc__format_from_version(&target_format, wc_format_version,
- scratch_pool));
+ if (wc_format_version == NULL && store_pristines == svn_tristate_unknown)
+ {
+ SVN_ERR(svn_wc__settings_from_context(&target_format,
+ &target_store_pristines,
+ ctx->wc_ctx, local_abspath,
+ scratch_pool));
+ }
else
- SVN_ERR(svn_wc__format_from_context(&target_format, ctx->wc_ctx,
- local_abspath, scratch_pool));
+ {
+ SVN_ERR_ASSERT(wc_format_version != NULL);
+ SVN_ERR(svn_wc__format_from_version(&target_format, wc_format_version,
+ scratch_pool));
+
+ SVN_ERR_ASSERT(store_pristines != svn_tristate_unknown);
+
+ if (store_pristines == svn_tristate_true)
+ target_store_pristines = TRUE;
+ else
+ target_store_pristines = FALSE;
+ }
+
/* Get the RA connection, if needed. */
if (ra_session)
{
@@ -158,7 +176,7 @@ svn_client__checkout_internal(svn_revnum_t *result
URL, revnum, and an 'incomplete' flag. */
SVN_ERR(svn_io_make_dir_recursively(local_abspath, scratch_pool));
SVN_ERR(initialize_area(target_format, local_abspath, pathrev, depth,
- ctx, scratch_pool));
+ target_store_pristines, ctx, scratch_pool));
}
else if (kind == svn_node_dir)
{
@@ -171,10 +189,25 @@ svn_client__checkout_internal(svn_revnum_t *result
if (! present_format)
{
SVN_ERR(initialize_area(target_format, local_abspath, pathrev, depth,
- ctx, scratch_pool));
+ target_store_pristines, ctx, scratch_pool));
}
else
{
+ svn_boolean_t wc_store_pristines;
+
+ SVN_ERR(svn_wc__get_settings(NULL, &wc_store_pristines, ctx->wc_ctx,
+ local_abspath, scratch_pool));
+
+ if ((target_store_pristines && !wc_store_pristines) ||
+ (!target_store_pristines && wc_store_pristines))
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_INCOMPATIBLE_SETTINGS, NULL,
+ _("'%s' is an existing working copy with different '%s'
setting"),
+ svn_dirent_local_style(local_abspath, scratch_pool),
+ "store-pristines");
+ }
+
/* Get PATH's URL. */
SVN_ERR(svn_wc__node_get_url(&entry_url, ctx->wc_ctx, local_abspath,
scratch_pool, scratch_pool));
@@ -228,6 +261,7 @@ svn_client_checkout4(svn_revnum_t *result_rev,
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
const svn_version_t *wc_format_version,
+ svn_tristate_t store_pristines,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -237,10 +271,27 @@ svn_client_checkout4(svn_revnum_t *result_rev,
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
- /* A NULL wc_format_version translates to the default version. */
+ if (store_pristines == svn_tristate_unknown)
+ store_pristines = svn_tristate_true;
+
+ /* A NULL wc_format_version translates to the minimum compatible version. */
if (!wc_format_version)
- wc_format_version = svn_client_default_wc_version(pool);
+ {
+ wc_format_version = svn_client_default_wc_version(pool);
+ if (store_pristines == svn_tristate_false)
+ {
+ const svn_version_t *required_version =
+ svn_client__compatible_wc_version_pristines_on_demand(pool);
+
+ if (!svn_version__at_least(wc_format_version,
+ required_version->major,
+ required_version->minor,
+ required_version->patch))
+ wc_format_version = required_version;
+ }
+ }
+
err = svn_client__checkout_internal(result_rev, &sleep_here,
URL, local_abspath,
peg_revision, revision, depth,
@@ -247,6 +298,7 @@ svn_client_checkout4(svn_revnum_t *result_rev,
ignore_externals,
allow_unver_obstructions,
wc_format_version,
+ store_pristines,
NULL /* ra_session */,
ctx, pool);
if (sleep_here)
Index: subversion/libsvn_client/client.h
===================================================================
--- subversion/libsvn_client/client.h (revision 1899956)
+++ subversion/libsvn_client/client.h (working copy)
@@ -540,10 +540,18 @@ svn_client__update_internal(svn_revnum_t *result_r
to fail.
A new working copy, if needed, will be created in the format corresponding
- to the WC_FORMAT_VERSION of the client. If this parameter is NULL, the
- format will be determined from context (see svn_wc__format_from_context).
- The format of any existing working copy will remain unchanged.
+ to the WC_FORMAT_VERSION of the client. The format of any existing working
+ copy will remain unchanged.
+ If STORE_PRISTINES is svn_tristate_true, the pristine contents of all
+ files in the working copy will be stored on disk. If STORE_PRISTINES is
+ svn_tristate_false, the pristine contents will be fetched on-demand when
+ required by the operation.
+
+ If WC_FORMAT_VERSION is NULL and STORE_PRISTINES is svn_tristate_unknown,
the
+ settings will be determined from context (see
svn_wc__settings_from_context).
+ Otherwise, both WC_FORMAT_VERSION and STORE_PRISTINES must be defined.
+
If RA_SESSION is NOT NULL, it may be used to avoid creating a new
session. The session may point to a different URL after returning.
*/
@@ -558,6 +566,7 @@ svn_client__checkout_internal(svn_revnum_t *result
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
const svn_version_t *wc_format_version,
+ svn_tristate_t store_pristines,
svn_ra_session_t *ra_session,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
@@ -1251,6 +1260,11 @@ svn_client__textbase_sync(const char *local_abspat
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool);
+/* Returns the first version that supported the working copy metadata format
+ * where pristines can be fetched on demand. */
+const svn_version_t *
+svn_client__compatible_wc_version_pristines_on_demand(apr_pool_t *result_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Index: subversion/libsvn_client/copy.c
===================================================================
--- subversion/libsvn_client/copy.c (revision 1899956)
+++ subversion/libsvn_client/copy.c (working copy)
@@ -2488,6 +2488,7 @@ svn_client__repos_to_wc_copy_dir(svn_boolean_t *ti
TRUE /*ignore_externals*/,
FALSE, /* we don't allow obstructions
*/
NULL, /* default WC format */
+ svn_tristate_unknown,
ra_session, ctx, scratch_pool);
ctx->notify_func2 = old_notify_func2;
Index: subversion/libsvn_client/deprecated.c
===================================================================
--- subversion/libsvn_client/deprecated.c (revision 1899956)
+++ subversion/libsvn_client/deprecated.c (working copy)
@@ -2683,7 +2683,8 @@ svn_client_checkout3(svn_revnum_t *result_rev,
return svn_error_trace(svn_client_checkout4(
result_rev, URL, path,
peg_revision, revision, depth,
- ignore_externals, FALSE, NULL, ctx, pool));
+ ignore_externals, FALSE, NULL,
+ svn_tristate_unknown, ctx, pool));
}
svn_error_t *
Index: subversion/libsvn_client/externals.c
===================================================================
--- subversion/libsvn_client/externals.c (revision 1899956)
+++ subversion/libsvn_client/externals.c (working copy)
@@ -413,6 +413,7 @@ switch_dir_external(const char *local_abspath,
revision, svn_depth_infinity,
FALSE, FALSE,
NULL, /* default WC format */
+ svn_tristate_unknown,
ra_session,
ctx, pool));
Index: subversion/libsvn_client/shelf.c
===================================================================
--- subversion/libsvn_client/shelf.c (revision 1899956)
+++ subversion/libsvn_client/shelf.c (working copy)
@@ -1034,6 +1034,7 @@ shelf_copy_base(svn_client__shelf_version_t *new_s
TRUE /*ignore_externals*/,
FALSE /*allow_unver_obstructions*/,
NULL, /* default WC format */
+ svn_tristate_unknown,
ra_session,
ctx, scratch_pool));
/* ### hopefully we won't eventually need to sleep_here... */
Index: subversion/libsvn_client/upgrade.c
===================================================================
--- subversion/libsvn_client/upgrade.c (revision 1899956)
+++ subversion/libsvn_client/upgrade.c (working copy)
@@ -93,6 +93,7 @@ static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
int wc_format,
+ svn_boolean_t store_pristines,
struct repos_info_baton *info_baton,
apr_pool_t *scratch_pool);
@@ -99,6 +100,7 @@ upgrade_externals_from_properties(svn_client_ctx_t
static svn_error_t *
upgrade_internal(const char *path,
int wc_format,
+ svn_boolean_t store_pristines,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
@@ -116,7 +118,8 @@ upgrade_internal(const char *path,
_("'%s' is not a local path"), path);
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
- SVN_ERR(svn_wc__upgrade(ctx->wc_ctx, local_abspath, wc_format,
+ SVN_ERR(svn_wc__upgrade(ctx->wc_ctx, local_abspath,
+ wc_format, store_pristines,
fetch_repos_info, &info_baton,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func2, ctx->notify_baton2,
@@ -155,7 +158,8 @@ upgrade_internal(const char *path,
if (kind == svn_node_dir)
{
svn_error_t *err = upgrade_internal(ext_abspath, wc_format,
- ctx, iterpool);
+ store_pristines, ctx,
+ iterpool);
if (err)
{
@@ -179,7 +183,8 @@ upgrade_internal(const char *path,
/* Upgrading from <= 1.6, or no svn:properties defined.
(There is no way to detect the difference from libsvn_client :( ) */
- SVN_ERR(upgrade_externals_from_properties(ctx, local_abspath, wc_format,
+ SVN_ERR(upgrade_externals_from_properties(ctx, local_abspath,
+ wc_format, store_pristines,
&info_baton, scratch_pool));
}
@@ -200,7 +205,7 @@ svn_client_upgrade2(const char *path,
SVN_ERR(svn_wc__format_from_version(&wc_format,
wc_format_version,
scratch_pool));
- SVN_ERR(upgrade_internal(path, wc_format, ctx, scratch_pool));
+ SVN_ERR(upgrade_internal(path, wc_format, TRUE, ctx, scratch_pool));
return SVN_NO_ERROR;
}
@@ -269,10 +274,21 @@ svn_client_latest_wc_version(apr_pool_t *result_po
return &version;
}
+const svn_version_t *
+svn_client__compatible_wc_version_pristines_on_demand(apr_pool_t *result_pool)
+{
+ /* NOTE: For consistency, always return the version of the client
+ that first introduced the format. */
+ static const svn_version_t version = { 1, 15, 0, NULL };
+ return &version;
+}
+
/* Helper for upgrade_externals_from_properties: upgrades one external ITEM
in EXTERNALS_PARENT. Uses SCRATCH_POOL for temporary allocations. */
static svn_error_t *
-upgrade_external_item(svn_client_ctx_t *ctx, int wc_format,
+upgrade_external_item(svn_client_ctx_t *ctx,
+ int wc_format,
+ svn_boolean_t store_pristines,
const char *externals_parent_abspath,
const char *externals_parent_url,
const char *externals_parent_repos_root_url,
@@ -315,7 +331,8 @@ static svn_error_t *
{
svn_error_clear(err);
- SVN_ERR(upgrade_internal(external_abspath, wc_format, ctx,
scratch_pool));
+ SVN_ERR(upgrade_internal(external_abspath, wc_format, store_pristines,
+ ctx, scratch_pool));
}
else if (err)
return svn_error_trace(err);
@@ -389,6 +406,7 @@ static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
int wc_format,
+ svn_boolean_t store_pristines,
struct repos_info_baton *info_baton,
apr_pool_t *scratch_pool)
{
@@ -477,7 +495,7 @@ upgrade_externals_from_properties(svn_client_ctx_t
item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
svn_pool_clear(inner_iterpool);
- err = upgrade_external_item(ctx, wc_format,
+ err = upgrade_external_item(ctx, wc_format, store_pristines,
externals_parent_abspath,
externals_parent_url,
externals_parent_repos_root_url,
Index: subversion/libsvn_wc/adm_files.c
===================================================================
--- subversion/libsvn_wc/adm_files.c (revision 1899956)
+++ subversion/libsvn_wc/adm_files.c (working copy)
@@ -207,6 +207,7 @@ init_adm(svn_wc__db_t *db,
const char *repos_uuid,
svn_revnum_t initial_rev,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *pool)
{
/* First, make an empty administrative area. */
@@ -228,7 +229,7 @@ init_adm(svn_wc__db_t *db,
/* Create the SDB. */
SVN_ERR(svn_wc__db_init(db, target_format, local_abspath,
repos_relpath, repos_root_url, repos_uuid,
- initial_rev, depth, pool));
+ initial_rev, depth, store_pristines, pool));
/* Stamp ENTRIES and FORMAT files for old clients. */
SVN_ERR(svn_io_file_create(svn_wc__adm_child(local_abspath,
@@ -254,6 +255,7 @@ svn_wc__internal_ensure_adm(svn_wc__db_t *db,
const char *repos_uuid,
svn_revnum_t revision,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool)
{
int present_format;
@@ -265,6 +267,7 @@ svn_wc__internal_ensure_adm(svn_wc__db_t *db,
svn_wc__db_status_t status;
const char *db_repos_relpath, *db_repos_root_url, *db_repos_uuid;
svn_revnum_t db_revision;
+ svn_boolean_t wc_store_pristines;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
SVN_ERR_ASSERT(url != NULL);
@@ -272,6 +275,24 @@ svn_wc__internal_ensure_adm(svn_wc__db_t *db,
SVN_ERR_ASSERT(repos_uuid != NULL);
SVN_ERR_ASSERT(repos_relpath != NULL);
+ if (target_format < SVN_WC__SUPPORTED_VERSION)
+ return svn_error_createf(
+ SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
+ _("Working copy format %d is not supported by client version %s."),
+ target_format, SVN_VER_NUM);
+
+ if (target_format > SVN_WC__VERSION)
+ return svn_error_createf(
+ SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
+ _("Working copy format %d can't be created by client version %s."),
+ target_format, SVN_VER_NUM);
+
+ if (target_format < SVN_WC__PRISTINES_ON_DEMAND_VERSION && !store_pristines)
+ return svn_error_createf(
+ SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
+ _("Working copy format %d does not support the requested
capabilities"),
+ target_format);
+
SVN_ERR(svn_wc__internal_check_wc(&present_format, db, local_abspath, TRUE,
scratch_pool));
@@ -279,24 +300,32 @@ svn_wc__internal_ensure_adm(svn_wc__db_t *db,
just create one. */
if (present_format == 0)
{
-
- if (target_format < SVN_WC__SUPPORTED_VERSION)
- return svn_error_createf(
- SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
- _("Working copy format %d is not supported by client version %s."),
- target_format, SVN_VER_NUM);
-
- if (target_format > SVN_WC__VERSION)
- return svn_error_createf(
- SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
- _("Working copy format %d can't be created by client version %s."),
- target_format, SVN_VER_NUM);
-
return svn_error_trace(init_adm(db, target_format, local_abspath,
repos_relpath, repos_root_url,
repos_uuid,
- revision, depth, scratch_pool));
+ revision, depth, store_pristines,
+ scratch_pool));
}
+ else if (present_format != target_format)
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+ _("Format %d doesn't match existing format %d in '%s'"),
+ target_format, present_format, local_abspath);
+ }
+ SVN_ERR(svn_wc__db_get_settings(NULL, &wc_store_pristines, db,
+ local_abspath, scratch_pool));
+
+ if ((store_pristines && !wc_store_pristines) ||
+ (!store_pristines && wc_store_pristines))
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_INCOMPATIBLE_SETTINGS, NULL,
+ _("'%s' is an existing working copy with different '%s' setting"),
+ svn_dirent_local_style(local_abspath, scratch_pool),
+ "store-pristines");
+ }
+
SVN_ERR(svn_wc__db_read_info(&status, NULL,
&db_revision, &db_repos_relpath,
&db_repos_root_url, &db_repos_uuid,
@@ -314,13 +343,6 @@ svn_wc__internal_ensure_adm(svn_wc__db_t *db,
if (status != svn_wc__db_status_deleted
&& status != svn_wc__db_status_not_present)
{
- /* Check that the existing format matches the requested format. */
- if (present_format != target_format)
- return svn_error_createf(
- SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
- _("Format %d doesn't match existing format %d in '%s'"),
- target_format, present_format, local_abspath);
-
/* ### Should we match copyfrom_revision? */
if (db_revision != revision)
return
@@ -389,12 +411,13 @@ svn_wc__ensure_adm(svn_wc_context_t *wc_ctx,
const char *repos_uuid,
svn_revnum_t revision,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool)
{
return svn_error_trace(
svn_wc__internal_ensure_adm(wc_ctx->db, target_format, local_abspath,
url, repos_root_url, repos_uuid, revision,
- depth, scratch_pool));
+ depth, store_pristines, scratch_pool));
}
svn_error_t *
Index: subversion/libsvn_wc/deprecated.c
===================================================================
--- subversion/libsvn_wc/deprecated.c (revision 1899956)
+++ subversion/libsvn_wc/deprecated.c (working copy)
@@ -582,7 +582,7 @@ svn_wc_ensure_adm4(svn_wc_context_t *wc_ctx,
return svn_error_trace(
svn_wc__ensure_adm(wc_ctx, SVN_WC__DEFAULT_VERSION, local_abspath,
url, repos_root_url, repos_uuid, revision, depth,
- scratch_pool));
+ TRUE, scratch_pool));
}
svn_error_t *
@@ -4900,7 +4900,7 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
void *notify_baton,
apr_pool_t *scratch_pool)
{
- return svn_wc__upgrade(wc_ctx, local_abspath, SVN_WC__DEFAULT_VERSION,
+ return svn_wc__upgrade(wc_ctx, local_abspath, SVN_WC__DEFAULT_VERSION, TRUE,
repos_info_func, repos_info_baton,
cancel_func, cancel_baton,
notify_func, notify_baton,
Index: subversion/libsvn_wc/info.c
===================================================================
--- subversion/libsvn_wc/info.c (revision 1899956)
+++ subversion/libsvn_wc/info.c (working copy)
@@ -106,8 +106,8 @@ build_info_for_node(svn_wc__info2_t **info,
wc_info->copyfrom_rev = SVN_INVALID_REVNUM;
- SVN_ERR(svn_wc__db_get_format(&wc_info->wc_format,
- db, local_abspath, scratch_pool));
+ SVN_ERR(svn_wc__db_get_settings(&wc_info->wc_format, NULL,
+ db, local_abspath, scratch_pool));
SVN_ERR(svn_wc__db_read_info(&status, &db_kind, &tmpinfo->rev,
&repos_relpath,
@@ -556,3 +556,16 @@ svn_wc__get_info(svn_wc_context_t *wc_ctx,
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_wc__get_settings(int *format_p,
+ svn_boolean_t *store_pristines_p,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(svn_wc__db_get_settings(format_p, store_pristines_p, wc_ctx->db,
+ local_abspath, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
Index: subversion/libsvn_wc/textbase.c
===================================================================
--- subversion/libsvn_wc/textbase.c (revision 1899956)
+++ subversion/libsvn_wc/textbase.c (working copy)
@@ -527,14 +527,14 @@ svn_wc__textbase_sync(svn_wc_context_t *wc_ctx,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
- const char *mode;
+ svn_boolean_t store_pristines;
textbase_sync_baton_t baton = {0};
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_pristines_mode(&mode, wc_ctx->db, local_abspath,
- scratch_pool));
- if (strcmp(mode, "local-only") == 0)
+ SVN_ERR(svn_wc__db_get_settings(NULL, &store_pristines, wc_ctx->db,
+ local_abspath, scratch_pool));
+ if (store_pristines)
return SVN_NO_ERROR;
baton.db = wc_ctx->db;
Index: subversion/libsvn_wc/upgrade.c
===================================================================
--- subversion/libsvn_wc/upgrade.c (revision 1899956)
+++ subversion/libsvn_wc/upgrade.c (working copy)
@@ -2026,6 +2026,7 @@ svn_error_t *
svn_wc__upgrade(svn_wc_context_t *wc_ctx,
const char *local_abspath,
int target_format,
+ svn_boolean_t store_pristines,
svn_wc_upgrade_get_repos_info_t repos_info_func,
void *repos_info_baton,
svn_cancel_func_t cancel_func,
@@ -2128,7 +2129,7 @@ svn_wc__upgrade(svn_wc_context_t *wc_ctx,
&data.repos_id, &data.wc_id,
db, target_format, data.root_abspath,
this_dir->repos, this_dir->uuid,
- scratch_pool));
+ store_pristines, scratch_pool));
/* Migrate the entries over to the new database.
### We need to think about atomicity here.
Index: subversion/libsvn_wc/wc-metadata.sql
===================================================================
--- subversion/libsvn_wc/wc-metadata.sql (revision 1899956)
+++ subversion/libsvn_wc/wc-metadata.sql (working copy)
@@ -713,7 +713,8 @@ WHERE l.op_depth = 0
following schema changes:
- Add the 'hydrated' column to the PRISTINE table.
- Add the I_PRISTINE_UNREFERENCED index.
- - Add the TEXTBASE_REFS table. */
+ - Add the TEXTBASE_REFS table.
+ - Add the SETTINGS table. */
-- STMT_UPGRADE_TO_32
/* True iff the pristine contents are currently available on disk. */
ALTER TABLE PRISTINE ADD COLUMN hydrated INTEGER NOT NULL DEFAULT 1;
@@ -778,6 +779,12 @@ BEGIN
AND op_depth = OLD.op_depth;
END;
+/* This table contains settings of a working copy, identified by WC_ID. */
+CREATE TABLE SETTINGS (
+ wc_id INTEGER NOT NULL REFERENCES WCROOT (id) PRIMARY KEY,
+ store_pristines INTEGER
+);
+
PRAGMA user_version = 32;
/* ------------------------------------------------------------------------- */
Index: subversion/libsvn_wc/wc-queries.sql
===================================================================
--- subversion/libsvn_wc/wc-queries.sql (revision 1899956)
+++ subversion/libsvn_wc/wc-queries.sql (working copy)
@@ -1896,6 +1896,14 @@ UNION ALL
SELECT pristine.checksum, pristine.hydrated, 0, NULL, NULL, NULL
FROM pristine WHERE refcount = 0
+-- STMT_SELECT_SETTINGS
+SELECT store_pristines FROM settings WHERE wc_id = ?1
+
+-- STMT_UPSERT_SETTINGS
+INSERT INTO settings (wc_id, store_pristines)
+VALUES (?1, ?2)
+ON CONFLICT(wc_id) DO UPDATE SET store_pristines=?2
+
/* ------------------------------------------------------------------------- */
/* Grab all the statements related to the schema. */
Index: subversion/libsvn_wc/wc.h
===================================================================
--- subversion/libsvn_wc/wc.h (revision 1899956)
+++ subversion/libsvn_wc/wc.h (working copy)
@@ -223,6 +223,9 @@ extern "C" {
* demand. */
#define SVN_WC__PRISTINES_ON_DEMAND_VERSION 32
+/* Starting from this version, the DB stores per-WC settings. */
+#define SVN_WC__SETTINGS_VERSION 32
+
/* Return a string indicating the released version (or versions) of
* Subversion that used WC format number WC_FORMAT, or some other
* suitable string if no released version used WC_FORMAT.
@@ -538,6 +541,7 @@ svn_wc__internal_ensure_adm(svn_wc__db_t *db,
const char *repos_uuid,
svn_revnum_t revision,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool);
Index: subversion/libsvn_wc/wc_db.c
===================================================================
--- subversion/libsvn_wc/wc_db.c (revision 1899956)
+++ subversion/libsvn_wc/wc_db.c (working copy)
@@ -1366,6 +1366,7 @@ init_db(/* output values */
const char *root_node_repos_relpath,
svn_revnum_t root_node_revision,
svn_depth_t root_node_depth,
+ svn_boolean_t store_pristines,
const char *wcroot_abspath,
apr_pool_t *scratch_pool)
{
@@ -1389,6 +1390,13 @@ init_db(/* output values */
SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_WCROOT));
SVN_ERR(svn_sqlite__insert(wc_id, stmt));
+ if (target_format >= SVN_WC__SETTINGS_VERSION)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_UPSERT_SETTINGS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "id", *wc_id, store_pristines));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+ }
+
if (root_node_repos_relpath)
{
svn_wc__db_status_t status = svn_wc__db_status_normal;
@@ -1436,6 +1444,7 @@ create_db(svn_sqlite__db_t **sdb,
const char *root_node_repos_relpath,
svn_revnum_t root_node_revision,
svn_depth_t root_node_depth,
+ svn_boolean_t store_pristines,
svn_boolean_t exclusive,
apr_int32_t timeout,
apr_pool_t *result_pool,
@@ -1450,7 +1459,8 @@ create_db(svn_sqlite__db_t **sdb,
SVN_SQLITE__WITH_LOCK(init_db(repos_id, wc_id,
*sdb, target_format, repos_root_url,
repos_uuid,
root_node_repos_relpath, root_node_revision,
- root_node_depth, dir_abspath, scratch_pool),
+ root_node_depth, store_pristines, dir_abspath,
+ scratch_pool),
*sdb);
return SVN_NO_ERROR;
@@ -1466,6 +1476,7 @@ svn_wc__db_init(svn_wc__db_t *db,
const char *repos_uuid,
svn_revnum_t initial_rev,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool)
{
svn_sqlite__db_t *sdb;
@@ -1495,7 +1506,7 @@ svn_wc__db_init(svn_wc__db_t *db,
/* Create the SDB and insert the basic rows. */
SVN_ERR(create_db(&sdb, &repos_id, &wc_id, target_format, local_abspath,
repos_root_url, repos_uuid, SDB_FILE,
- repos_relpath, initial_rev, depth,
+ repos_relpath, initial_rev, depth, store_pristines,
sqlite_exclusive, sqlite_timeout,
db->state_pool, scratch_pool));
@@ -1504,6 +1515,7 @@ svn_wc__db_init(svn_wc__db_t *db,
apr_pstrdup(db->state_pool, local_abspath),
sdb, wc_id, FORMAT_FROM_SDB,
FALSE /* auto-upgrade */,
+ store_pristines,
db->state_pool, scratch_pool));
/* Any previously cached children may now have a new WCROOT, most likely that
@@ -1537,10 +1549,11 @@ svn_wc__db_init(svn_wc__db_t *db,
svn_error_t *
-svn_wc__db_get_format(int *format,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
+svn_wc__db_get_settings(int *format_p,
+ svn_boolean_t *store_pristines_p,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
@@ -1552,7 +1565,11 @@ svn_error_t *
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- *format = wcroot->format;
+ if (format_p)
+ *format_p = wcroot->format;
+ if (store_pristines_p)
+ *store_pristines_p = wcroot->store_pristines;
+
return SVN_NO_ERROR;
}
@@ -13442,6 +13459,7 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_t **sdb,
const char *dir_abspath,
const char *repos_root_url,
const char *repos_uuid,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool)
{
svn_wc__db_wcroot_t *wcroot;
@@ -13451,6 +13469,7 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_t **sdb,
dir_abspath, repos_root_url, repos_uuid,
SDB_FILE,
NULL, SVN_INVALID_REVNUM, svn_depth_unknown,
+ store_pristines,
TRUE /* exclusive */,
0 /* timeout */,
wc_db->state_pool, scratch_pool));
@@ -13460,6 +13479,7 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_t **sdb,
dir_abspath),
*sdb, *wc_id, FORMAT_FROM_SDB,
FALSE /* auto-upgrade */,
+ store_pristines,
wc_db->state_pool, scratch_pool));
/* The WCROOT is complete. Stash it into DB. */
Index: subversion/libsvn_wc/wc_db.h
===================================================================
--- subversion/libsvn_wc/wc_db.h (revision 1899956)
+++ subversion/libsvn_wc/wc_db.h (working copy)
@@ -310,17 +310,20 @@ svn_wc__db_init(svn_wc__db_t *db,
const char *repos_uuid,
svn_revnum_t initial_rev,
svn_depth_t depth,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool);
-/* Return the working copy format for LOCAL_ABSPATH in DB in *FORMAT.
+/* Return the working copy settings *FORMAT_P and *STORE_PRISTINES_P for
+ LOCAL_ABSPATH in DB.
Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
-svn_wc__db_get_format(int *format,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
+svn_wc__db_get_settings(int *format_p,
+ svn_boolean_t *store_pristines_p,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool);
/* Compute the LOCAL_RELPATH for the given LOCAL_ABSPATH, relative
from wri_abspath.
@@ -1086,14 +1089,6 @@ svn_wc__db_pristine_dehydrate(svn_wc__db_t *db,
const svn_checksum_t *sha1_checksum,
apr_pool_t *scratch_pool);
-/* Return the *PRISTINES_MODE for the WC at (DB, LOCAL_ABSPATH).
- */
-svn_error_t *
-svn_wc__db_pristines_mode(const char **pristines_mode,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
-
/* @defgroup svn_wc__db_external External management
@{ */
@@ -2988,6 +2983,7 @@ svn_wc__db_upgrade_begin(svn_sqlite__db_t **sdb,
const char *local_dir_abspath,
const char *repos_root_url,
const char *repos_uuid,
+ svn_boolean_t store_pristines,
apr_pool_t *scratch_pool);
/* Simply insert (or replace) one row in the EXTERNALS table. */
Index: subversion/libsvn_wc/wc_db_pristine.c
===================================================================
--- subversion/libsvn_wc/wc_db_pristine.c (revision 1899956)
+++ subversion/libsvn_wc/wc_db_pristine.c (working copy)
@@ -418,7 +418,7 @@ svn_wc__db_pristine_prepare_install(svn_stream_t *
install_data = apr_pcalloc(result_pool, sizeof(*install_data));
install_data->wcroot = wcroot;
- if (hydrated || strcmp(wcroot->pristines_mode, "local-only") == 0)
+ if (hydrated || wcroot->store_pristines)
{
SVN_ERR_W(svn_stream__create_for_install(&install_data->inner_stream,
temp_dir_abspath,
Index: subversion/libsvn_wc/wc_db_private.h
===================================================================
--- subversion/libsvn_wc/wc_db_private.h (revision 1899956)
+++ subversion/libsvn_wc/wc_db_private.h (working copy)
@@ -107,8 +107,9 @@ typedef struct svn_wc__db_wcroot_t {
const char *local_abspath -> svn_wc_adm_access_t *adm_access */
apr_hash_t *access_cache;
- /* How to manage the pristines ("local-only" or "on-demand") */
- const char *pristines_mode;
+ /* Whether to store the pristine contents of all files on disk or
+ to fetch the contents on demand. */
+ svn_boolean_t store_pristines;
} svn_wc__db_wcroot_t;
@@ -129,6 +130,7 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t *
apr_int64_t wc_id,
int format,
svn_boolean_t verify_format,
+ svn_boolean_t store_pristines,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
Index: subversion/libsvn_wc/wc_db_wcroot.c
===================================================================
--- subversion/libsvn_wc/wc_db_wcroot.c (revision 1899956)
+++ subversion/libsvn_wc/wc_db_wcroot.c (working copy)
@@ -303,6 +303,7 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t *
apr_int64_t wc_id,
int format,
svn_boolean_t verify_format,
+ svn_boolean_t store_pristines,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -390,12 +391,7 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t *
(*wcroot)->owned_locks = apr_array_make(result_pool, 8,
sizeof(svn_wc__db_wclock_t));
(*wcroot)->access_cache = apr_hash_make(result_pool);
- /* Determine the pristines-mode for this WC. */
- /* ### TODO: read this from per-WC storage instead of locked to wc format */
- if (format < SVN_WC__PRISTINES_ON_DEMAND_VERSION)
- (*wcroot)->pristines_mode = "local-only";
- else
- (*wcroot)->pristines_mode = "on-demand";
+ (*wcroot)->store_pristines = store_pristines;
/* SDB will be NULL for pre-NG working copies. We only need to run a
cleanup when the SDB is present. */
@@ -502,6 +498,38 @@ verify_stats_table(svn_sqlite__db_t *sdb,
return SVN_NO_ERROR;
}
+/* Read and return the settings for WC_ID in SDB. */
+static svn_error_t *
+read_settings(svn_boolean_t *store_pristines_p,
+ svn_sqlite__db_t *sdb,
+ int format,
+ apr_int64_t wc_id,
+ apr_pool_t *scratch_pool)
+{
+ if (format >= SVN_WC__SETTINGS_VERSION)
+ {
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_SETTINGS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "i", wc_id));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (have_row)
+ *store_pristines_p = svn_sqlite__column_boolean(stmt, 0);
+ else
+ *store_pristines_p = TRUE;
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
+ else
+ {
+ *store_pristines_p = TRUE;
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Sqlite transaction helper for opening the db in
svn_wc__db_wcroot_parse_local_abspath() to avoid multiple
db operations that each obtain and release a lock */
@@ -508,6 +536,7 @@ verify_stats_table(svn_sqlite__db_t *sdb,
static svn_error_t *
fetch_sdb_info(apr_int64_t *wc_id,
int *format,
+ svn_boolean_t *store_pristines,
svn_sqlite__db_t *sdb,
apr_pool_t *scratch_pool)
{
@@ -518,7 +547,7 @@ fetch_sdb_info(apr_int64_t *wc_id,
svn_wc__db_util_fetch_wc_id(wc_id, sdb, scratch_pool),
svn_sqlite__read_schema_version(format, sdb, scratch_pool),
verify_stats_table(sdb, *format, scratch_pool),
- SVN_NO_ERROR,
+ read_settings(store_pristines, sdb, *format, *wc_id, scratch_pool),
sdb);
return SVN_NO_ERROR;
@@ -771,9 +800,10 @@ try_symlink_as_dir:
apr_int64_t wc_id;
int format;
+ svn_boolean_t store_pristines;
svn_error_t *err;
- err = fetch_sdb_info(&wc_id, &format, sdb, scratch_pool);
+ err = fetch_sdb_info(&wc_id, &format, &store_pristines, sdb,
scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_WC_CORRUPT)
@@ -794,6 +824,7 @@ try_symlink_as_dir:
: local_abspath),
sdb, wc_id, format,
db->verify_format,
+ store_pristines,
db->state_pool, scratch_pool);
if (err && (err->apr_err == SVN_ERR_WC_UNSUPPORTED_FORMAT ||
err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED) &&
@@ -869,6 +900,7 @@ try_symlink_as_dir:
: local_abspath),
NULL, UNKNOWN_WC_ID, wc_format,
db->verify_format,
+ TRUE,
db->state_pool, scratch_pool));
}
@@ -1047,10 +1079,11 @@ svn_wc__db_drop_root(svn_wc__db_t *db,
* TODO: Convert the svn_wc__db_t::dir_data hash to a sorted dictionary?.
*/
svn_error_t *
-svn_wc__format_from_context(int *format,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
+svn_wc__settings_from_context(int *format_p,
+ svn_boolean_t *store_pristines_p,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
{
apr_hash_t *const dir_data = wc_ctx->db->dir_data;
apr_array_header_t *keys;
@@ -1060,7 +1093,8 @@ svn_error_t *
SVN_ERR(svn_hash_keys(&keys, dir_data, scratch_pool));
if (0 == keys->nelts)
{
- *format = SVN_WC__DEFAULT_VERSION;
+ *format_p = SVN_WC__DEFAULT_VERSION;
+ *store_pristines_p = TRUE;
return SVN_NO_ERROR;
}
@@ -1082,7 +1116,8 @@ svn_error_t *
{
/* Found an exact match in the WC context. */
svn_wc__db_wcroot_t *wcroot = svn_hash_gets(dir_data, here);
- *format = wcroot->format;
+ *format_p = wcroot->format;
+ *store_pristines_p = wcroot->store_pristines;
return SVN_NO_ERROR;
}
}
@@ -1094,7 +1129,8 @@ svn_error_t *
{
/* Found the parent path in the WC context. */
svn_wc__db_wcroot_t *wcroot = svn_hash_gets(dir_data, prev);
- *format = wcroot->format;
+ *format_p = wcroot->format;
+ *store_pristines_p = wcroot->store_pristines;
return SVN_NO_ERROR;
}
}
@@ -1103,6 +1139,7 @@ svn_error_t *
/* Find the oldest format recorded in the WC context. */
{
int oldest_format = SVN_WC__VERSION;
+ svn_boolean_t store_pristines = TRUE;
apr_hash_index_t *hi;
for (hi = apr_hash_first(scratch_pool, dir_data);
@@ -1111,28 +1148,14 @@ svn_error_t *
{
svn_wc__db_wcroot_t *wcroot = apr_hash_this_val(hi);
if (wcroot->format < oldest_format)
- oldest_format = wcroot->format;
+ {
+ oldest_format = wcroot->format;
+ store_pristines = wcroot->store_pristines;
+ }
}
- *format = oldest_format;
+ *format_p = oldest_format;
+ *store_pristines_p = store_pristines;
return SVN_NO_ERROR;
}
}
-
-svn_error_t *
-svn_wc__db_pristines_mode(const char **pristines_mode,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_wcroot_t *wcroot;
- const char *local_relpath;
-
- SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
- local_abspath, scratch_pool,
- scratch_pool));
- VERIFY_USABLE_WCROOT(wcroot);
-
- *pristines_mode = wcroot->pristines_mode;
- return SVN_NO_ERROR;
-}
Index: subversion/svn/checkout-cmd.c
===================================================================
--- subversion/svn/checkout-cmd.c (revision 1899956)
+++ subversion/svn/checkout-cmd.c (working copy)
@@ -173,6 +173,7 @@ svn_cl__checkout(apr_getopt_t *os,
opt_state->ignore_externals,
opt_state->force,
opt_state->compatible_version,
+ opt_state->store_pristines,
ctx, subpool));
}
svn_pool_destroy(subpool);
Index: subversion/svn/cl.h
===================================================================
--- subversion/svn/cl.h (revision 1899956)
+++ subversion/svn/cl.h (working copy)
@@ -276,6 +276,7 @@ typedef struct svn_cl__opt_state_t
svn_cl__viewspec_svn11
} viewspec; /* value of --x-viewspec */
svn_version_t *compatible_version; /* working copy compatibility version */
+ svn_boolean_t store_pristines;
} svn_cl__opt_state_t;
/* Conflict stats for operations such as update and merge. */
@@ -376,6 +377,7 @@ typedef enum svn_cl__longopt_t {
opt_drop,
opt_viewspec,
opt_compatible_version,
+ opt_store_pristines
} svn_cl__longopt_t;
/* Options for giving a log message. (Some of these also have other uses.)
Index: subversion/svn/svn.c
===================================================================
--- subversion/svn/svn.c (revision 1899956)
+++ subversion/svn/svn.c (working copy)
@@ -371,6 +371,17 @@ const apr_getopt_option_t svn_cl__options[] =
" "
"version ARG (\"1.8\", \"1.9.5\", etc.)")},
+ {"store-pristines", opt_store_pristines, 1,
+ N_("Configure the working copy to either store local\n"
+ " "
+ "copies of pristine contents ('yes') or to fetch\n"
+ " "
+ "them on demand ('no'). Fetching on demand saves\n"
+ " "
+ "disk space, but may require network access for\n"
+ " "
+ "commands such as diff or revert. Default: 'yes'.")},
+
/* Long-opt Aliases
*
* These have NULL descriptions, but an option code that matches some
@@ -543,7 +554,7 @@ svn_cl__cmd_table_main[] =
" reporting the action taken.\n"
)},
{'r', 'q', 'N', opt_depth, opt_force, opt_ignore_externals,
- opt_compatible_version},
+ opt_compatible_version, opt_store_pristines},
{{'N', N_("obsolete; same as --depth=files")}} },
{ "cleanup", svn_cl__cleanup, {0}, {N_(
@@ -2178,6 +2189,7 @@ sub_main(int *exit_code, int argc, const char *arg
opt_state.accept_which = svn_cl__accept_unspecified;
opt_state.show_revs = svn_cl__show_revs_invalid;
opt_state.file_size_unit = SVN_CL__SIZE_UNIT_NONE;
+ opt_state.store_pristines = svn_tristate_unknown;
/* No args? Show usage. */
if (argc <= 1)
@@ -2734,6 +2746,15 @@ sub_main(int *exit_code, int argc, const char *arg
case opt_compatible_version:
SVN_ERR(parse_compatible_version(&opt_state, opt_arg, pool));
break;
+ case opt_store_pristines:
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.store_pristines = svn_tristate__from_word(utf8_opt_arg);
+ if (opt_state.store_pristines == svn_tristate_unknown)
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Unknown value '%s' for %s.\n"
+ "Supported values: %s"),
+ utf8_opt_arg, "--store-pristines", "yes,
no");
+ break;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
Index: subversion/tests/libsvn_client/client-test.c
===================================================================
--- subversion/tests/libsvn_client/client-test.c (revision 1899956)
+++ subversion/tests/libsvn_client/client-test.c (working copy)
@@ -392,7 +392,9 @@ test_patch(const svn_test_opts_t *opts,
SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path,
&peg_rev, &rev, svn_depth_infinity,
TRUE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
/* Create the patch file. */
patch_file_path = svn_dirent_join_many(
@@ -466,13 +468,17 @@ test_wc_add_scenarios(const svn_test_opts_t *opts,
/* Checkout greek tree as wc_path */
SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path, &peg_rev, &rev,
svn_depth_infinity, FALSE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
/* Now checkout again as wc_path/NEW */
new_dir_path = svn_dirent_join(wc_path, "NEW", pool);
SVN_ERR(svn_client_checkout4(NULL, repos_url, new_dir_path, &peg_rev, &rev,
svn_depth_infinity, FALSE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
ex_dir_path = svn_dirent_join(wc_path, "NEW_add", pool);
ex2_dir_path = svn_dirent_join(wc_path, "NEW_add2", pool);
@@ -632,7 +638,9 @@ test_16k_add(const svn_test_opts_t *opts,
SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path,
&peg_rev, &rev, svn_depth_infinity,
TRUE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
for (i = 0; i < 16384; i++)
{
@@ -763,7 +771,9 @@ test_foreign_repos_copy(const svn_test_opts_t *opt
SVN_ERR(svn_client_checkout4(NULL, repos_url, wc_path, &peg_rev, &rev,
svn_depth_infinity,
FALSE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
repos2_url, NULL, &peg_rev, &rev,
@@ -832,7 +842,9 @@ test_suggest_mergesources(const svn_test_opts_t *o
wc_path,
&head_rev, &head_rev, svn_depth_empty,
FALSE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
SVN_ERR(svn_client_suggest_merge_sources(&results,
wc_path,
@@ -979,7 +991,9 @@ test_remote_only_status(const svn_test_opts_t *opt
apr_pstrcat(pool, repos_url, "/A", SVN_VA_NULL),
wc_path, &rev, &rev, svn_depth_immediates,
FALSE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
/* Add a local file; this is a double-check to make sure that
remote-only status ignores local changes. */
Index: subversion/tests/libsvn_client/conflicts-test.c
===================================================================
--- subversion/tests/libsvn_client/conflicts-test.c (revision 1899956)
+++ subversion/tests/libsvn_client/conflicts-test.c (working copy)
@@ -6117,7 +6117,9 @@ test_file_vs_dir_move_merge_assertion_failure(cons
"A1", pool),
wc_path, &peg_rev, &opt_rev, svn_depth_infinity,
TRUE, FALSE,
- opts->wc_format_version, ctx, pool));
+ opts->wc_format_version,
+ opts->store_pristines,
+ ctx, pool));
SVN_ERR(svn_client_merge_peg5(svn_path_url_add_component2(b->repos_url, "A",
pool),
Index: subversion/tests/libsvn_wc/entries-compat.c
===================================================================
--- subversion/tests/libsvn_wc/entries-compat.c (revision 1899956)
+++ subversion/tests/libsvn_wc/entries-compat.c (working copy)
@@ -644,7 +644,7 @@ test_access_baton_like_locking(const svn_test_opts
svn_path_url_add_component2(url, "sub-wc",
pool),
repos_root_url, repos_uuid,
0, svn_depth_infinity,
- pool));
+ opts->store_pristines, pool));
SVN_ERR(svn_wc__db_is_switched(&is_root, NULL, NULL, wc_ctx->db, subdir,
pool));
Index: subversion/tests/libsvn_wc/utils.c
===================================================================
--- subversion/tests/libsvn_wc/utils.c (revision 1899956)
+++ subversion/tests/libsvn_wc/utils.c (working copy)
@@ -108,6 +108,7 @@ create_repos_and_wc(const char **repos_url,
FALSE /* ignore_externals */,
FALSE /* allow_unver_obstructions */,
opts->wc_format_version,
+ opts->store_pristines,
ctx, subpool));
svn_pool_destroy(subpool);
}
Index: subversion/tests/libsvn_wc/wc-queries-test.c
===================================================================
--- subversion/tests/libsvn_wc/wc-queries-test.c (revision 1899956)
+++ subversion/tests/libsvn_wc/wc-queries-test.c (working copy)
@@ -256,6 +256,8 @@ stmt_matches_wc_format(int stmt_num,
case STMT_TEXTBASE_REMOVE_REF:
case STMT_TEXTBASE_WALK:
case STMT_TEXTBASE_SYNC:
+ case STMT_SELECT_SETTINGS:
+ case STMT_UPSERT_SETTINGS:
return (wc_format >= 32);
}
return TRUE;
Index: subversion/tests/svn_test.h
===================================================================
--- subversion/tests/svn_test.h (revision 1899956)
+++ subversion/tests/svn_test.h (working copy)
@@ -219,6 +219,7 @@ typedef struct svn_test_opts_t
/* WC format version to use for all tests (except tests for a specific
format) */
const svn_version_t *wc_format_version;
svn_boolean_t verbose;
+ svn_tristate_t store_pristines;
/* Add future "arguments" here. */
} svn_test_opts_t;
Index: subversion/tests/svn_test_main.c
===================================================================
--- subversion/tests/svn_test_main.c (revision 1899956)
+++ subversion/tests/svn_test_main.c (working copy)
@@ -809,6 +809,7 @@ svn_test_main(int argc, const char *argv[], int ma
opts.fs_type = DEFAULT_FS_TYPE;
opts.wc_format_version = svn_wc__min_supported_format_version();
+ opts.store_pristines = svn_tristate_unknown;
/* Initialize APR (Apache pools) */
if (apr_initialize() != APR_SUCCESS)
Index: tools/client-side/bash_completion
===================================================================
--- tools/client-side/bash_completion (revision 1899956)
+++ tools/client-side/bash_completion (working copy)
@@ -882,7 +882,7 @@ _svn()
;;
checkout|co)
cmdOpts="$rOpts $qOpts $nOpts $pOpts --ignore-externals \
- --force"
+ --force --store-pristines"
;;
cleanup)
cmdOpts="$pOpts --include-externals -q --quiet\