You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ko...@apache.org on 2022/12/13 09:49:30 UTC

svn commit: r1905955 [1/6] - in /subversion/trunk: ./ build/ build/generator/ notes/i525/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_x/ subversion/libsvn_ra/ subversion/libsvn_ra_local/ subversion/lib...

Author: kotkov
Date: Tue Dec 13 09:49:29 2022
New Revision: 1905955

URL: http://svn.apache.org/viewvc?rev=1905955&view=rev
Log:
Merge the `pristines-on-demand-on-mwf` branch to trunk.

What's included
---------------

- Core implementation of the new mode where required pristines are fetched
  at the beginning of the operation.

- A new --store-pristine=yes/no option for `svn checkout` that is persisted
  as a working copy setting.

- An update for `svn info` to display the value of this new setting.

- A standalone test harness that tests main operations in both
  --store-pristine modes and gets executed on every test run.

- A new --store-pristine=yes/no option for the test suite that forces all
  tests to run with a specific pristine mode.


Description of the approach in the new mode
-------------------------------------------

The core idea is that we start to maintain the following invariant: only the
modified files have their pristine text-base files available on the disk.

- To avoid having to access the text-base, the "is the file modified?" check
  is performed by calculating the checksum of a file and comparing that to
  what's recorded in the working copy.

- A text-base of the unmodified file is the file itself, appropriately
  detranslated.

- To get into the appropriate state at the beginning of the operation, we walk
  through the current text-base info in the db and check if the corresponding
  working files are modified.  The missing text-bases are fetched using the
  svn_ra layer.  The operations also include a final step during which the
  no longer required text-bases are removed from disk.

- The operations that don't need to access the text-bases (such as "svn ls"
  or the updated "svn st") do not perform this walk and do not synchronize
  the text-base state.


References
----------

[1] https://issues.apache.org/jira/browse/SVN-525
[2] https://lists.apache.org/thread/f3nrp0q2qtqbngg92897rhkkgx8qs8sp
[3] https://lists.apache.org/thread/rx975btbtwx2klj8ykmz4t3v8vx49kjn

Added:
    subversion/trunk/notes/i525/
      - copied from r1905954, subversion/branches/pristines-on-demand-on-mwf/notes/i525/
    subversion/trunk/subversion/libsvn_client/textbase.c
      - copied unchanged from r1905954, subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_client/textbase.c
    subversion/trunk/subversion/libsvn_wc/textbase.c
      - copied unchanged from r1905954, subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/textbase.c
    subversion/trunk/subversion/libsvn_wc/textbase.h
      - copied unchanged from r1905954, subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/textbase.h
    subversion/trunk/subversion/libsvn_wc/wc_db_textbase.c
      - copied unchanged from r1905954, subversion/branches/pristines-on-demand-on-mwf/subversion/libsvn_wc/wc_db_textbase.c
    subversion/trunk/subversion/tests/cmdline/store_pristine_tests.py
      - copied unchanged from r1905954, subversion/branches/pristines-on-demand-on-mwf/subversion/tests/cmdline/store_pristine_tests.py
Modified:
    subversion/trunk/   (props changed)
    subversion/trunk/INSTALL
    subversion/trunk/Makefile.in
    subversion/trunk/build/generator/gen_win_dependencies.py
    subversion/trunk/build/run_tests.py
    subversion/trunk/configure.ac
    subversion/trunk/get-deps.sh
    subversion/trunk/subversion/include/private/svn_wc_private.h
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/include/svn_ra.h
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_client/cat.c
    subversion/trunk/subversion/libsvn_client/checkout.c
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/commit.c
    subversion/trunk/subversion/libsvn_client/commit_util.c
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/libsvn_client/copy.c
    subversion/trunk/subversion/libsvn_client/deprecated.c
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_client/export.c
    subversion/trunk/subversion/libsvn_client/externals.c
    subversion/trunk/subversion/libsvn_client/layout.c
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/ra.c
    subversion/trunk/subversion/libsvn_client/resolved.c
    subversion/trunk/subversion/libsvn_client/revert.c
    subversion/trunk/subversion/libsvn_client/shelf.c
    subversion/trunk/subversion/libsvn_client/shelf2.c
    subversion/trunk/subversion/libsvn_client/status.c
    subversion/trunk/subversion/libsvn_client/switch.c
    subversion/trunk/subversion/libsvn_client/update.c
    subversion/trunk/subversion/libsvn_client/upgrade.c
    subversion/trunk/subversion/libsvn_client/util.c
    subversion/trunk/subversion/libsvn_fs_x/   (props changed)
    subversion/trunk/subversion/libsvn_ra/ra_loader.c
    subversion/trunk/subversion/libsvn_ra/ra_loader.h
    subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
    subversion/trunk/subversion/libsvn_ra_serf/get_file.c
    subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
    subversion/trunk/subversion/libsvn_ra_serf/serf.c
    subversion/trunk/subversion/libsvn_ra_svn/client.c
    subversion/trunk/subversion/libsvn_subr/sqlite.c
    subversion/trunk/subversion/libsvn_subr/utf8proc/   (props changed)
    subversion/trunk/subversion/libsvn_wc/adm_crawler.c
    subversion/trunk/subversion/libsvn_wc/adm_files.c
    subversion/trunk/subversion/libsvn_wc/adm_files.h
    subversion/trunk/subversion/libsvn_wc/adm_ops.c
    subversion/trunk/subversion/libsvn_wc/conflicts.c
    subversion/trunk/subversion/libsvn_wc/copy.c
    subversion/trunk/subversion/libsvn_wc/deprecated.c
    subversion/trunk/subversion/libsvn_wc/diff_editor.c
    subversion/trunk/subversion/libsvn_wc/diff_local.c
    subversion/trunk/subversion/libsvn_wc/externals.c
    subversion/trunk/subversion/libsvn_wc/info.c
    subversion/trunk/subversion/libsvn_wc/merge.c
    subversion/trunk/subversion/libsvn_wc/questions.c
    subversion/trunk/subversion/libsvn_wc/revert.c
    subversion/trunk/subversion/libsvn_wc/update_editor.c
    subversion/trunk/subversion/libsvn_wc/upgrade.c
    subversion/trunk/subversion/libsvn_wc/util.c
    subversion/trunk/subversion/libsvn_wc/wc-metadata.sql
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc.h
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h
    subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c
    subversion/trunk/subversion/libsvn_wc/wc_db_private.h
    subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
    subversion/trunk/subversion/libsvn_wc/wc_db_wcroot.c
    subversion/trunk/subversion/svn/checkout-cmd.c
    subversion/trunk/subversion/svn/cl.h
    subversion/trunk/subversion/svn/info-cmd.c
    subversion/trunk/subversion/svn/notify.c
    subversion/trunk/subversion/svn/schema/info.rnc
    subversion/trunk/subversion/svn/svn.c
    subversion/trunk/subversion/tests/cmdline/authz_tests.py
    subversion/trunk/subversion/tests/cmdline/basic_tests.py
    subversion/trunk/subversion/tests/cmdline/diff_tests.py
    subversion/trunk/subversion/tests/cmdline/externals_tests.py
    subversion/trunk/subversion/tests/cmdline/move_tests.py
    subversion/trunk/subversion/tests/cmdline/revert_tests.py
    subversion/trunk/subversion/tests/cmdline/svntest/actions.py
    subversion/trunk/subversion/tests/cmdline/svntest/main.py
    subversion/trunk/subversion/tests/cmdline/svntest/mergetrees.py
    subversion/trunk/subversion/tests/cmdline/svntest/wc.py
    subversion/trunk/subversion/tests/cmdline/trans_tests.py
    subversion/trunk/subversion/tests/cmdline/update_tests.py
    subversion/trunk/subversion/tests/cmdline/upgrade_tests.py
    subversion/trunk/subversion/tests/libsvn_client/client-test.c
    subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c
    subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c
    subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
    subversion/trunk/subversion/tests/libsvn_wc/pristine-store-test.c
    subversion/trunk/subversion/tests/libsvn_wc/utils.c
    subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c
    subversion/trunk/subversion/tests/libsvn_wc/wc-test-queries.sql
    subversion/trunk/subversion/tests/libsvn_wc/wc-test.c
    subversion/trunk/subversion/tests/svn_test.h
    subversion/trunk/subversion/tests/svn_test_main.c
    subversion/trunk/tools/buildbot/slaves/win32-vcpkg/   (props changed)
    subversion/trunk/tools/client-side/bash_completion
    subversion/trunk/win-tests.py

Propchange: subversion/trunk/
------------------------------------------------------------------------------
  Merged /subversion/branches/pristines-on-demand-on-mwf:r1897945-1898738,1898742-1898996,1898998-1899653,1899655-1905954
  Merged /subversion/branches/pristines-on-demand:r1892643-1897397,1897400-1897945

Modified: subversion/trunk/INSTALL
URL: http://svn.apache.org/viewvc/subversion/trunk/INSTALL?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/INSTALL (original)
+++ subversion/trunk/INSTALL Tue Dec 13 09:49:29 2022
@@ -262,7 +262,7 @@ I.    INTRODUCTION
 
       2.  SQLite  (REQUIRED)
 
-      Subversion requires SQLite version 3.8.2 or above.  You can meet this
+      Subversion requires SQLite version 3.24.0 or above.  You can meet this
       dependency several ways:
         * Use an SQLite amalgamation file.
         * Specify an SQLite installation to use.
@@ -841,8 +841,8 @@ II.   INSTALLATION
         1.4 or later (1.2 for apr-iconv). If you are building from a Subversion
         checkout and have not downloaded Apache 2, then get these 3 libraries
         from https://www.apache.org/dist/apr/.
-      * SQLite 3.8.2 or higher from https://www.sqlite.org/download.html
-        (3.8.11.1 or higher recommended)
+      * SQLite 3.24.0 or higher from https://www.sqlite.org/download.html
+        (3.39.4 or higher recommended)
       * ZLib 1.2 or higher is required and can be obtained from
         http://www.zlib.net/
       * Either a Subversion client binary from

Modified: subversion/trunk/Makefile.in
URL: http://svn.apache.org/viewvc/subversion/trunk/Makefile.in?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/Makefile.in (original)
+++ subversion/trunk/Makefile.in Tue Dec 13 09:49:29 2022
@@ -629,6 +629,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
 	  if test "$(SVN_BIN_DIR)" != ""; then                               \
 	    flags="--bin $(SVN_BIN_DIR) $$flags";                            \
 	  fi;                                                                \
+	  if test "$(STORE_PRISTINE)" != ""; then                            \
+	    flags="--store-pristine $(STORE_PRISTINE) $$flags";              \
+	  fi;                                                                \
 	  LD_LIBRARY_PATH='$(auth_plugin_dirs):$(LD_LIBRARY_PATH)'           \
 	  $(PYTHON) $(top_srcdir)/build/run_tests.py                         \
 	            --config-file $(top_srcdir)/subversion/tests/tests.conf  \

Modified: subversion/trunk/build/generator/gen_win_dependencies.py
URL: http://svn.apache.org/viewvc/subversion/trunk/build/generator/gen_win_dependencies.py?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/build/generator/gen_win_dependencies.py (original)
+++ subversion/trunk/build/generator/gen_win_dependencies.py Tue Dec 13 09:49:29 2022
@@ -1482,7 +1482,7 @@ class GenDependenciesBase(gen_base.Gener
   def _find_sqlite(self, show_warnings):
     "Find the Sqlite library and version"
 
-    minimal_sqlite_version = (3, 8, 2)
+    minimal_sqlite_version = (3, 24, 0)
 
     # For SQLite we support 3 scenarios:
     # - Installed in standard directory layout

Modified: subversion/trunk/build/run_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/build/run_tests.py?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/build/run_tests.py (original)
+++ subversion/trunk/build/run_tests.py Tue Dec 13 09:49:29 2022
@@ -35,7 +35,7 @@
             [--config-file=<file>] [--ssl-cert=<file>]
             [--exclusive-wc-locks] [--memcached-server=<url:port>]
             [--fsfs-compression=<type>] [--fsfs-dir-deltification=<true|false>]
-            [--allow-remote-http-connection]
+            [--allow-remote-http-connection] [--store-pristine=<val>]
             <abs_srcdir> <abs_builddir>
             <prog ...>
 
@@ -264,6 +264,8 @@ class TestHarness:
       cmdline.append('--mode-filter=' + self.opts.mode_filter)
     if self.opts.parallel is not None:
       cmdline.append('--parallel')
+    if self.opts.store_pristine is not None:
+      cmdline.append('--store-pristine=%s' % self.opts.store_pristine)
 
     self.c_test_cmdline = cmdline
 
@@ -331,6 +333,8 @@ class TestHarness:
       cmdline.append('--fsfs-dir-deltification=%s' % self.opts.fsfs_dir_deltification)
     if self.opts.allow_remote_http_connection is not None:
       cmdline.append('--allow-remote-http-connection')
+    if self.opts.store_pristine is not None:
+      cmdline.append('--store-pristine=%s' % self.opts.store_pristine)
 
     self.py_test_cmdline = cmdline
 
@@ -1089,6 +1093,8 @@ def create_parser():
                     help='Set directory deltification option (for fsfs)')
   parser.add_option('--allow-remote-http-connection', action='store_true',
                     help='Run tests that connect to remote HTTP(S) servers')
+  parser.add_option('--store-pristine', action='store', type='str',
+                    help='Set the WC pristine mode')
 
   parser.set_defaults(set_log_level=None)
   return parser

Modified: subversion/trunk/configure.ac
URL: http://svn.apache.org/viewvc/subversion/trunk/configure.ac?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/configure.ac (original)
+++ subversion/trunk/configure.ac Tue Dec 13 09:49:29 2022
@@ -178,10 +178,10 @@ SVN_FIND_APACHE(20051115, $apache_whitel
 dnl Search for SQLite.  If you change SQLITE_URL from a .zip to
 dnl something else also update build/ac-macros/sqlite.m4 to reflect
 dnl the correct command to unpack the downloaded file.
-SQLITE_MINIMUM_VER="3.8.2"
-SQLITE_RECOMMENDED_VER="3.8.11.1"
+SQLITE_MINIMUM_VER="3.24.0"
+SQLITE_RECOMMENDED_VER="3.39.4"
 dnl Used to construct the SQLite download URL.
-SQLITE_RECOMMENDED_VER_REL_YEAR="2015"
+SQLITE_RECOMMENDED_VER_REL_YEAR="2022"
 SQLITE_URL="https://www.sqlite.org/$SQLITE_RECOMMENDED_VER_REL_YEAR/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip"
 
 SVN_LIB_SQLITE(${SQLITE_MINIMUM_VER}, ${SQLITE_RECOMMENDED_VER},

Modified: subversion/trunk/get-deps.sh
URL: http://svn.apache.org/viewvc/subversion/trunk/get-deps.sh?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/get-deps.sh (original)
+++ subversion/trunk/get-deps.sh Tue Dec 13 09:49:29 2022
@@ -36,9 +36,9 @@ APU_VERSION=${APU_VERSION:-"1.5.1"}
 PY3C_VERSION=${PY3C_VERSION:='1.1'}
 SERF_VERSION=${SERF_VERSION:-"1.3.8"}
 ZLIB_VERSION=${ZLIB_VERSION:-"1.2.8"}
-SQLITE_VERSION=${SQLITE_VERSION:-"3.8.11.1"}
+SQLITE_VERSION=${SQLITE_VERSION:-"3.39.4"}
 # Used to construct the SQLite download URL.
-SQLITE_VERSION_REL_YEAR=2015
+SQLITE_VERSION_REL_YEAR=2022
 HTTPD_VERSION=${HTTPD_VERSION:-"2.4.10"}
 APR_ICONV_VERSION=${APR_ICONV_VERSION:-"1.2.1"}
 

Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Tue Dec 13 09:49:29 2022
@@ -1040,7 +1040,7 @@ svn_wc__node_get_md5_from_sha1(const svn
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
-/* Like svn_wc_get_pristine_contents2(), but keyed on the CHECKSUM
+/* Like svn_wc_get_pristine_contents3(), but keyed on the CHECKSUM
    rather than on the local absolute path of the working file.
    WRI_ABSPATH is any versioned path of the working copy in whose
    pristine database we'll be looking for these contents.  */
@@ -1657,7 +1657,7 @@ svn_wc__get_switch_editor(const svn_delt
  *      |    |          |       |          |       |          |       out
  *      |    +----------+       +----------+       +----------+
  *      |
- *   3. svn_wc_crawl_revisions5(WC,reporter)
+ *   3. svn_wc_crawl_revisions6(WC,reporter)
  *
  *
  * @since New in 1.8.
@@ -2081,18 +2081,18 @@ svn_wc__acquire_write_lock_for_resolve(c
                                        apr_pool_t *result_pool,
                                        apr_pool_t *scratch_pool);
 
-/* The implementation of svn_wc_diff6(), but reporting to a diff processor
+/* The implementation of svn_wc_diff7(), but reporting to a diff processor
  *
  * New mode, when ANCHOR_AT_GIVEN_PATHS is true:
  *
  *   Anchor the DIFF_PROCESSOR at LOCAL_ABSPATH.
  *
- * Backward compatibility mode for svn_wc_diff6(),
+ * Backward compatibility mode for svn_wc_diff7(),
  * when ANCHOR_AT_GIVEN_PATHS is false:
  *
  *   Send diff processor relpaths relative to LOCAL_ABSPATH if it is a
  *   directory; otherwise, relative to the parent of LOCAL_ABSPATH.
- *   This matches the "anchor and target" semantics of svn_wc_diff6().
+ *   This matches the "anchor and target" semantics of svn_wc_diff7().
  */
 svn_error_t *
 svn_wc__diff7(svn_boolean_t anchor_at_given_paths,
@@ -2231,25 +2231,27 @@ 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 library's default format if
- * there are no such roots.
+ * Set @a *format_p and @a *store_pristine_p to the settings of the
+ * nearest parent working copy root of @a local_abspath in @a wc_ctx,
+ * or to the library's default settings if there are no such roots.
  *
  * Use @a scratch_pool for temporary allocations.
  *
  * @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_pristine_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_pristine 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 +2282,13 @@ svn_wc__ensure_adm(svn_wc_context_t *wc_
                    const char *repos_uuid,
                    svn_revnum_t revision,
                    svn_depth_t depth,
+                   svn_boolean_t store_pristine,
                    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_pristine
+ * 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 +2310,7 @@ svn_error_t *
 svn_wc__upgrade(svn_wc_context_t *wc_ctx,
                 const char *local_abspath,
                 int target_format,
+                svn_boolean_t store_pristine,
                 svn_wc_upgrade_get_repos_info_t repos_info_func,
                 void *repos_info_baton,
                 svn_cancel_func_t cancel_func,
@@ -2314,6 +2319,15 @@ svn_wc__upgrade(svn_wc_context_t *wc_ctx
                 void *notify_baton,
                 apr_pool_t *scratch_pool);
 
+/* Return the working copy settings *FORMAT_P and *STORE_PRISTINE_P for
+   LOCAL_ABSPATH in WC_CTX. */
+svn_error_t *
+svn_wc__get_settings(int *format_p,
+                     svn_boolean_t *store_pristine_p,
+                     svn_wc_context_t *wc_ctx,
+                     const char *local_abspath,
+                     apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Tue Dec 13 09:49:29 2022
@@ -1245,6 +1245,11 @@ svn_client_args_to_target_array(apr_arra
  *              @c NULL means the library's version.
  *              See svn_client_default_wc_version(),
  *              svn_client_get_wc_formats_supported().
+ * @param[in] store_pristine  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 *resul
                      svn_boolean_t ignore_externals,
                      svn_boolean_t allow_unver_obstructions,
                      const svn_version_t *wc_format_version,
+                     svn_tristate_t store_pristine,
                      svn_client_ctx_t *ctx,
                      apr_pool_t *pool);
 

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Tue Dec 13 09:49:29 2022
@@ -576,6 +576,22 @@ 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")
+
+  /** @since New in 1.15 */
+  SVN_ERRDEF(SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE,
+             SVN_ERR_WC_CATEGORY_START + 43,
+             "This client uses a deprecated API that does not support "
+             "working copies without local pristines")
+
+  /** @since New in 1.15 */
+  SVN_ERRDEF(SVN_ERR_WC_PRISTINE_DEHYDRATED,
+             SVN_ERR_WC_CATEGORY_START + 44,
+             "No local pristine contents for a file")
+
   /* fs errors */
 
   SVN_ERRDEF(SVN_ERR_FS_GENERAL,

Modified: subversion/trunk/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_ra.h?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_ra.h (original)
+++ subversion/trunk/subversion/include/svn_ra.h Tue Dec 13 09:49:29 2022
@@ -2164,6 +2164,29 @@ svn_ra_get_inherited_props(svn_ra_sessio
                            apr_pool_t *scratch_pool);
 
 /**
+ * Fetch the contents of file @a path at @a revision.  Interpret @a path
+ * relative to the URL in @a session.  @a revision must be a valid revision
+ * number.  Use @a scratch_pool for scratch allocations.
+ *
+ * The contents of the file will be pushed to @a stream, and the stream will
+ * be closed when finished.  If the closure is not desired, then you can use
+ * svn_stream_disown() to protect the stream from being closed.  The stream
+ * handlers for @a stream may not perform any RA operations using @a session.
+ *
+ * The contents may be expected to be fetched directly from the remote
+ * endpoint, rather from any local caches such as the one provided by
+ * #svn_ra_get_wc_contents_func_t.
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_ra_fetch_file_contents(svn_ra_session_t *session,
+                           const char *path,
+                           svn_revnum_t revision,
+                           svn_stream_t *stream,
+                           apr_pool_t *scratch_pool);
+
+/**
  * @defgroup Capabilities Dynamically query the server's capabilities.
  *
  * @{

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Tue Dec 13 09:49:29 2022
@@ -1305,6 +1305,22 @@ typedef enum svn_wc_notify_action_t
    * @since New in 1.10. */
   svn_wc_notify_end_search_tree_conflict_details,
 
+  /** Hydrating (fetching text-bases): starting a batch of fetching
+   * within the WC subtree at @c svn_wc_notify_t.path. (Zero or more files
+   * may be fetched, each preceded by @c svn_wc_notify_hydrating_file.)
+   * @since New in 1.15. */
+  svn_wc_notify_hydrating_start,
+
+  /** Hydrating (fetching text-bases): about to fetch a file
+   * from @c svn_wc_notify_t.url at @c svn_wc_notify_t.revision.
+   * @since New in 1.15. */
+  svn_wc_notify_hydrating_file,
+
+  /** Hydrating (fetching text-bases): finished a batch of fetching
+   * within the WC subtree at @c svn_wc_notify_t.path.
+   * @since New in 1.15. */
+  svn_wc_notify_hydrating_end,
+
   /** A warning, specified in #svn_wc_notify_t.err.
    * @since New in 1.15. */
   svn_wc_notify_warning,
@@ -3298,6 +3314,12 @@ typedef struct svn_wc_info_t
    * @since New in 1.15.
    */
   int wc_format;
+
+  /**
+   * Whether pristine content is stored locally or is being fetched on-demand.
+   * @since New in 1.15.
+   */
+  svn_boolean_t store_pristine;
 } svn_wc_info_t;
 
 /**
@@ -5527,10 +5549,48 @@ svn_wc_process_committed(const char *pat
  * @a notify_baton and the path of the restored file. @a notify_func may
  * be @c NULL if this notification is not required.  If @a
  * use_commit_times is TRUE, then set restored files' timestamps to
- * their last-commit-times.
+ * their last-commit-times.  For working copies that do not store local
+ * pristine contents for all files, return @c SVN_ERR_WC_PRISTINE_DEHYDRATED
+ * on an attempt to restore a file whose pristine contents is not present
+ * locally.
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_crawl_revisions6(svn_wc_context_t *wc_ctx,
+                        const char *local_abspath,
+                        const svn_ra_reporter3_t *reporter,
+                        void *report_baton,
+                        svn_boolean_t restore_files,
+                        svn_depth_t depth,
+                        svn_boolean_t honor_depth_exclude,
+                        svn_boolean_t depth_compatibility_trick,
+                        svn_boolean_t use_commit_times,
+                        svn_cancel_func_t cancel_func,
+                        void *cancel_baton,
+                        svn_wc_notify_func2_t notify_func,
+                        void *notify_baton,
+                        apr_pool_t *scratch_pool);
+
+/**
+ * Similar to svn_wc_crawl_revisions6, but if @a restore_files is @c TRUE,
+ * this function can only be used for working copies that store local
+ * copies of all pristine contents.
+ *
+ * If @a restore_files is @c TRUE and a working copy doesn't store local copies
+ * of all pristine contents, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE
+ * error will be returned.
  *
  * @since New in 1.7.
+ * @deprecated Provided for compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_crawl_revisions5(svn_wc_context_t *wc_ctx,
                         const char *local_abspath,
@@ -6758,8 +6818,45 @@ svn_wc_get_diff_editor(svn_wc_adm_access
  * points during the operation.  If it returns an error (typically
  * #SVN_ERR_CANCELLED), return that error immediately.
  *
+ * For working copies that do not store local pristine contents for all
+ * files, return @c SVN_ERR_WC_PRISTINE_DEHYDRATED on an attempt to diff
+ * a file whose pristine contents is not present locally.
+ *
+ * @note For general purposes, please consider using APIs from svn_client.h,
+ * @see svn_client_diff7().
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_diff7(svn_wc_context_t *wc_ctx,
+             const char *target_abspath,
+             const svn_wc_diff_callbacks4_t *callbacks,
+             void *callback_baton,
+             svn_depth_t depth,
+             svn_boolean_t ignore_ancestry,
+             svn_boolean_t show_copies_as_adds,
+             svn_boolean_t use_git_diff_format,
+             const apr_array_header_t *changelist_filter,
+             svn_cancel_func_t cancel_func,
+             void *cancel_baton,
+             apr_pool_t *scratch_pool);
+
+/**
+ * Similar to svn_wc_diff7(), but this function can only be used for
+ * working copies that store local copies of all pristine contents.
+ * Otherwise, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE error will be
+ * returned.
+ *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_diff6(svn_wc_context_t *wc_ctx,
              const char *target_abspath,
@@ -7021,8 +7118,50 @@ typedef enum svn_wc_merge_outcome_t
  *
  * Use @a scratch_pool for any temporary allocation.
  *
+ * For working copies that do not store local pristine contents for all
+ * files, return @c SVN_ERR_WC_PRISTINE_DEHYDRATED on an attempt to merge
+ * a file whose pristine contents is not present locally.
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_merge6(enum svn_wc_merge_outcome_t *merge_content_outcome,
+              enum svn_wc_notify_state_t *merge_props_state,
+              svn_wc_context_t *wc_ctx,
+              const char *left_abspath,
+              const char *right_abspath,
+              const char *target_abspath,
+              const char *left_label,
+              const char *right_label,
+              const char *target_label,
+              const svn_wc_conflict_version_t *left_version,
+              const svn_wc_conflict_version_t *right_version,
+              svn_boolean_t dry_run,
+              const char *diff3_cmd,
+              const apr_array_header_t *merge_options,
+              apr_hash_t *original_props,
+              const apr_array_header_t *prop_diff,
+              svn_wc_conflict_resolver_func2_t conflict_func,
+              void *conflict_baton,
+              svn_cancel_func_t cancel_func,
+              void *cancel_baton,
+              apr_pool_t *scratch_pool);
+
+/** Similar to svn_wc_merge6(), but this function can only be used
+ * for working copies that store local copies of all pristine contents.
+ * Otherwise, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE error will be
+ * returned.
+ *
  * @since New in 1.8.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
               enum svn_wc_notify_state_t *merge_props_state,
@@ -7292,7 +7431,36 @@ svn_wc_merge_prop_diffs(svn_wc_notify_st
  * @c SVN_ERR_WC_PATH_NOT_FOUND. Use @a wc_ctx to access the working copy.
  * @a contents may not be @c NULL (unlike @a *contents).
  *
- * @since New in 1.7. */
+ * For working copies that do not store local pristine contents for all
+ * files, the function may return a detranslated stream to the contents
+ * of the file itself if the file is not modified.  If the file is
+ * modified and its pristine contents is not present locally, return
+ * @c SVN_ERR_WC_PRISTINE_DEHYDRATED.
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_get_pristine_contents3(svn_stream_t **contents,
+                              svn_wc_context_t *wc_ctx,
+                              const char *local_abspath,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
+/** Similar to svn_wc_get_pristine_contents3, but this function can only be used
+ * for working copies that store local copies of all pristine contents.
+ * Otherwise, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE error will be
+ * returned.
+ *
+ * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
+ */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_get_pristine_contents2(svn_stream_t **contents,
                               svn_wc_context_t *wc_ctx,
@@ -7336,6 +7504,60 @@ svn_wc_get_pristine_copy_path(const char
                               apr_pool_t *pool);
 
 
+/** The callback invoked by svn_wc_textbase_sync() to provide the text-base
+ * contents identified by @a repos_root_url, @a repos_relpath and @a revision.
+ *
+ * The callback is expected to write the contents to @a contents and close
+ * the stream.
+ *
+ * @since New in 1.15.
+ */
+typedef svn_error_t *(*svn_wc_textbase_fetch_cb_t)(
+  void *baton,
+  const char *repos_root_url,
+  const char *repos_relpath,
+  svn_revnum_t revision,
+  svn_stream_t *contents,
+  svn_cancel_func_t cancel_func,
+  void *cancel_baton,
+  apr_pool_t *scratch_pool);
+
+/** Synchronize the state of the text-base contents for the
+ * @a local_abspath tree.
+ *
+ * If @a allow_hydrate is true, fetch the required but missing text-base
+ * contents using the provided @a fetch_callback and @a fetch_baton.
+ * If @a allow_hydrate is false, @a fetch_callback will not be used and
+ * may be @c NULL.
+ *
+ * If @a allow_dehydrate is true, remove the on disk text-base contents
+ * that is not required.
+ *
+ * If @a cancel_func is non-NULL, invoke it with @a cancel_baton at various
+ * points during the operation.  If it returns an error (typically
+ * #SVN_ERR_CANCELLED), return that error immediately.
+ *
+ * If @a notify_func is non-NULL, invoke it with @a notify_baton to report
+ * the progress of the operation.
+ *
+ * @see svn_wc_textbase_fetch_cb_t
+ * @see svn_client__textbase_sync for usage/implementation example.
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_textbase_sync(svn_wc_context_t *wc_ctx,
+                     const char *local_abspath,
+                     svn_boolean_t allow_hydrate,
+                     svn_boolean_t allow_dehydrate,
+                     svn_wc_textbase_fetch_cb_t fetch_callback,
+                     void *fetch_baton,
+                     svn_cancel_func_t cancel_func,
+                     void *cancel_baton,
+                     svn_wc_notify_func2_t notify_func,
+                     void *notify_baton,
+                     apr_pool_t *scratch_pool);
+
 /**
  * Recurse from @a local_abspath, cleaning up unfinished tasks.  Perform
  * any temporary allocations in @a scratch_pool.  If @a break_locks is TRUE
@@ -7646,8 +7868,45 @@ svn_wc_relocate(const char *path,
  * If @a path is not under version control, return the error
  * #SVN_ERR_UNVERSIONED_RESOURCE.
  *
+ * For working copies that do not store local pristine contents for all
+ * files, return @c SVN_ERR_WC_PRISTINE_DEHYDRATED on an attempt to revert
+ * a file whose pristine contents is not present locally.
+ *
+ * @note For general purposes, please consider using APIs from svn_client.h,
+ * @see svn_client_revert4().
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_revert7(svn_wc_context_t *wc_ctx,
+               const char *local_abspath,
+               svn_depth_t depth,
+               svn_boolean_t use_commit_times,
+               const apr_array_header_t *changelist_filter,
+               svn_boolean_t clear_changelists,
+               svn_boolean_t metadata_only,
+               svn_boolean_t added_keep_local,
+               svn_cancel_func_t cancel_func,
+               void *cancel_baton,
+               svn_wc_notify_func2_t notify_func,
+               void *notify_baton,
+               apr_pool_t *scratch_pool);
+
+/** Similar to svn_wc_revert7(), but this function can only be used
+ * for working copies that store local copies of all pristine contents.
+ * Otherwise, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE error will be
+ * returned.
+ *
  * @since New in 1.11.
+ * @deprecated Provided for backward compatibility with the 1.11 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_revert6(svn_wc_context_t *wc_ctx,
                const char *local_abspath,
@@ -7773,8 +8032,34 @@ svn_wc_revert(const char *path,
  * SVN_ERROR_WC_PATH_UNEXPECTED_STATUS if LOCAL_ABSPATH is in a status where
  * it can't be restored.
  *
+ * For working copies that do not store local pristine contents for all
+ * files, return @c SVN_ERR_WC_PRISTINE_DEHYDRATED on an attempt to restore
+ * a file whose pristine contents is not present locally.
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_restore2(svn_wc_context_t *wc_ctx,
+                const char *local_abspath,
+                svn_boolean_t use_commit_times,
+                apr_pool_t *scratch_pool);
+
+/**
+ * Similar to svn_wc_restore2(), but this function can only be used
+ * for working copies that store local copies of all pristine contents.
+ * Otherwise, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE error will be
+ * returned.
+ *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_restore(svn_wc_context_t *wc_ctx,
                const char *local_abspath,
@@ -7943,8 +8228,37 @@ svn_wc_translated_stream(svn_stream_t **
  * @note This is intended for use with both infix and postfix
  * text-delta styled editor drivers.
  *
+ * @note For general purposes, please consider using APIs from svn_client.h,
+ * @see svn_client_commit6().
+ *
+ * @note This is a relatively low-level function operating directly on a
+ * working copy, so a caller is expected to be able to handle working copies
+ * that do not store local copies of all pristine contents.  This can be
+ * achieved by synchronizing the text-base state before and optionally
+ * after the function call.  @see svn_wc_textbase_sync().
+ *
+ * @since New in 1.15.
+ */
+svn_error_t *
+svn_wc_transmit_text_deltas4(const svn_checksum_t **new_text_base_md5_checksum,
+                             const svn_checksum_t **new_text_base_sha1_checksum,
+                             svn_wc_context_t *wc_ctx,
+                             const char *local_abspath,
+                             svn_boolean_t fulltext,
+                             const svn_delta_editor_t *editor,
+                             void *file_baton,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool);
+
+/** Similar to svn_wc_transmit_text_deltas4(), but this function can only be
+ * used for working copies that store local copies of all pristine contents.
+ * Otherwise, an #SVN_ERR_WC_DEPRECATED_API_STORE_PRISTINE error will be
+ * returned.
+ *
  * @since New in 1.7.
+ * @deprecated Provided for backwards compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_transmit_text_deltas3(const svn_checksum_t **new_text_base_md5_checksum,
                              const svn_checksum_t **new_text_base_sha1_checksum,

Modified: subversion/trunk/subversion/libsvn_client/cat.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/cat.c?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/cat.c (original)
+++ subversion/trunk/subversion/libsvn_client/cat.c Tue Dec 13 09:49:29 2022
@@ -85,7 +85,7 @@ svn_client__get_normalized_stream(svn_st
 
   if (revision->kind != svn_opt_revision_working)
     {
-      SVN_ERR(svn_wc_get_pristine_contents2(&input, wc_ctx, local_abspath,
+      SVN_ERR(svn_wc_get_pristine_contents3(&input, wc_ctx, local_abspath,
                                             result_pool, scratch_pool));
       if (input == NULL)
         return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -216,6 +216,11 @@ svn_client_cat3(apr_hash_t **returned_pr
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url,
                                       scratch_pool));
+
+      /* This will open the RA session internally if needed. */
+      SVN_ERR(svn_client__textbase_sync(NULL, local_abspath, TRUE, TRUE, ctx,
+                                        NULL, scratch_pool, scratch_pool));
+
       SVN_ERR(svn_client__get_normalized_stream(&normal_stream, ctx->wc_ctx,
                                             local_abspath, revision,
                                             expand_keywords, FALSE,
@@ -229,9 +234,14 @@ svn_client_cat3(apr_hash_t **returned_pr
         SVN_ERR(svn_wc_prop_list2(returned_props, ctx->wc_ctx, local_abspath,
                                   result_pool, scratch_pool));
 
-      return svn_error_trace(svn_stream_copy3(normal_stream, output,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, scratch_pool));
+      SVN_ERR(svn_stream_copy3(normal_stream, output,
+                               ctx->cancel_func,
+                               ctx->cancel_baton, scratch_pool));
+
+      SVN_ERR(svn_client__textbase_sync(NULL, local_abspath, FALSE, TRUE, ctx,
+                                        NULL, scratch_pool, scratch_pool));
+
+      return SVN_NO_ERROR;
     }
 
   /* Get an RA plugin for this filesystem object. */

Modified: subversion/trunk/subversion/libsvn_client/checkout.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/checkout.c?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/checkout.c (original)
+++ subversion/trunk/subversion/libsvn_client/checkout.c Tue Dec 13 09:49:29 2022
@@ -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_pristine,
                 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_pristine, pool));
   return SVN_NO_ERROR;
 }
 
@@ -78,11 +81,13 @@ svn_client__checkout_internal(svn_revnum
                               svn_boolean_t ignore_externals,
                               svn_boolean_t allow_unver_obstructions,
                               const svn_version_t *wc_format_version,
+                              svn_tristate_t store_pristine,
                               svn_ra_session_t *ra_session,
                               svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
   int target_format;
+  svn_boolean_t target_store_pristine;
   svn_node_kind_t kind;
   svn_client__pathrev_t *pathrev;
   svn_opt_revision_t resolved_rev = { svn_opt_revision_number };
@@ -98,14 +103,27 @@ svn_client__checkout_internal(svn_revnum
       && (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_pristine == svn_tristate_unknown)
+    {
+      SVN_ERR(svn_wc__settings_from_context(&target_format,
+                                            &target_store_pristine,
+                                            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_pristine != svn_tristate_unknown);
+
+      if (store_pristine == svn_tristate_true)
+        target_store_pristine = TRUE;
+      else
+        target_store_pristine = FALSE;
+    }
 
   /* Get the RA connection, if needed. */
   if (ra_session)
@@ -158,7 +176,7 @@ svn_client__checkout_internal(svn_revnum
          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_pristine, ctx, scratch_pool));
     }
   else if (kind == svn_node_dir)
     {
@@ -171,10 +189,25 @@ svn_client__checkout_internal(svn_revnum
       if (! present_format)
         {
           SVN_ERR(initialize_area(target_format, local_abspath, pathrev, depth,
-                                  ctx, scratch_pool));
+                                  target_store_pristine, ctx, scratch_pool));
         }
       else
         {
+          svn_boolean_t wc_store_pristine;
+
+          SVN_ERR(svn_wc__get_settings(NULL, &wc_store_pristine, ctx->wc_ctx,
+                                       local_abspath, scratch_pool));
+
+          if ((target_store_pristine && !wc_store_pristine) ||
+              (!target_store_pristine && wc_store_pristine))
+            {
+              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-pristine");
+            }
+
           /* 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 *resul
                      svn_boolean_t ignore_externals,
                      svn_boolean_t allow_unver_obstructions,
                      const svn_version_t *wc_format_version,
+                     svn_tristate_t store_pristine,
                      svn_client_ctx_t *ctx,
                      apr_pool_t *pool)
 {
@@ -237,9 +271,26 @@ svn_client_checkout4(svn_revnum_t *resul
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
-  /* A NULL wc_format_version translates to the default version. */
+  if (store_pristine == svn_tristate_unknown)
+    store_pristine = 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_pristine == svn_tristate_false)
+        {
+          const svn_version_t *required_version =
+            svn_client__compatible_wc_version_optional_pristine(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,
@@ -247,6 +298,7 @@ svn_client_checkout4(svn_revnum_t *resul
                                       ignore_externals,
                                       allow_unver_obstructions,
                                       wc_format_version,
+                                      store_pristine,
                                       NULL /* ra_session */,
                                       ctx, pool);
   if (sleep_here)

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Tue Dec 13 09:49:29 2022
@@ -540,9 +540,17 @@ svn_client__update_internal(svn_revnum_t
    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_PRISTINE is svn_tristate_true, the pristine contents of all
+   files in the working copy will be stored on disk.  If STORE_PRISTINE 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_PRISTINE is svn_tristate_unknown, the
+   settings will be determined from context (see svn_wc__settings_from_context).
+   Otherwise, both WC_FORMAT_VERSION and STORE_PRISTINE 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
                               svn_boolean_t ignore_externals,
                               svn_boolean_t allow_unver_obstructions,
                               const svn_version_t *wc_format_version,
+                              svn_tristate_t store_pristine,
                               svn_ra_session_t *ra_session,
                               svn_client_ctx_t *ctx,
                               apr_pool_t *pool);
@@ -1242,6 +1251,35 @@ svn_client__merge_locked(svn_client__con
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Synchronize the state of the text-base contents for the LOCAL_ABSPATH tree.
+ *
+ * If ALLOW_HYDRATE is true, fetch the required but missing text-base contents.
+ * If ALLOW_DEHYDRATE is true, remove the on disk text-base contents that are
+ * not required.
+ *
+ * The missing contents will be fetched using the provided RA_SESSION if it
+ * is not NULL.  If RA_SESSION is NULL and some of the text-bases have to be
+ * fetched, a new RA session will be opened internally.  If RA_SESSION_P is
+ * not NULL, the session used during fetch will be returned in *RA_SESSION_P.
+ * If this is the session that was opened internally, it will be allocated in
+ * RESULT_POOL.  Note that *RA_SESSION_P may be set to NULL if no fetching
+ * took place.
+ */
+svn_error_t *
+svn_client__textbase_sync(svn_ra_session_t **ra_session_p,
+                          const char *local_abspath,
+                          svn_boolean_t allow_hydrate,
+                          svn_boolean_t allow_dehydrate,
+                          svn_client_ctx_t *ctx,
+                          svn_ra_session_t *ra_session,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool);
+
+/* Returns the first version that supported the working copy metadata format
+ * where pristine content is optional and can be fetched on demand. */
+const svn_version_t *
+svn_client__compatible_wc_version_optional_pristine(apr_pool_t *result_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit.c?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit.c Tue Dec 13 09:49:29 2022
@@ -708,6 +708,10 @@ svn_client_commit6(const apr_array_heade
                                                    pool, pool));
     }
 
+  /* Optimization: for commit, we avoid fetching the text-bases at the
+     beginning of the operation and only delta against the text-bases that
+     are available locally.  See svn_wc__internal_transmit_text_deltas(). */
+
   SVN_ERR(determine_lock_targets(&lock_targets, ctx->wc_ctx, base_abspath,
                                  rel_targets, pool, iterpool));
 
@@ -1075,6 +1079,12 @@ svn_client_commit6(const apr_array_heade
           svn_pool_clear(iterpool);
 
           unlock_err = svn_error_compose_create(
+                           svn_client__textbase_sync(NULL, lock_root,
+                                                     FALSE, TRUE, ctx,
+                                                     NULL, iterpool, iterpool),
+                           unlock_err);
+
+          unlock_err = svn_error_compose_create(
                            svn_wc__release_write_lock(ctx->wc_ctx, lock_root,
                                                       iterpool),
                            unlock_err);

Modified: subversion/trunk/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit_util.c?rev=1905955&r1=1905954&r2=1905955&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit_util.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit_util.c Tue Dec 13 09:49:29 2022
@@ -1937,7 +1937,7 @@ svn_client__do_commit(const char *base_u
           && ! (item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY))
         fulltext = TRUE;
 
-      err = svn_wc_transmit_text_deltas3(&new_text_base_md5_checksum,
+      err = svn_wc_transmit_text_deltas4(&new_text_base_md5_checksum,
                                          &new_text_base_sha1_checksum,
                                          ctx->wc_ctx, item->path,
                                          fulltext, editor, mod->file_baton,