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 2021/08/27 13:52:21 UTC

svn commit: r1892646 - /subversion/branches/pristines-on-demand/subversion/libsvn_wc/questions.c

Author: kotkov
Date: Fri Aug 27 13:52:21 2021
New Revision: 1892646

URL: http://svn.apache.org/viewvc?rev=1892646&view=rev
Log:
On the pristines-on-demand branch: Don't read the pristine text even
when checking for file modifications in the "exact comparison" mode.

Previously for that kind of comparison we'd check if the pristine text
translated according to the file props matches the current contents of
the file.  This allows detecting modifications that are otherwise missed
by the non-exact comparison where we check if the *detranslated* contents
of the file matches the pristine.  One example of a modification that is
only detected in the exact comparison mode is a file with manually
contracted svn:keywords.

To make this work without a pristine text, let's check for two things:

1) That the checksum of the detranslated contents matches the recorded
   pristine checksum, as in the case of a non-exact comparison, …

2) …and additionally, that the contents of the working file does not
   change when retranslated according to its properties.

Technically we're going to do that with a single read of the file contents,
while checksumming it's original, detranslated and retranslated versions.

* subversion/libsvn_wc/questions.c
  (compare_and_verify): Check for an unrecognized eol-style value when
   fetching the file props, allowing for an early error-out.  When asked
   to perform an exact comparison, calculate checksums for the original,
   detranslated and retranslated versions of the working file.  Compare the
   detranslated-pristine and original-retranslated checksum pairs to see
   if the file is modified.

Modified:
    subversion/branches/pristines-on-demand/subversion/libsvn_wc/questions.c

Modified: subversion/branches/pristines-on-demand/subversion/libsvn_wc/questions.c
URL: http://svn.apache.org/viewvc/subversion/branches/pristines-on-demand/subversion/libsvn_wc/questions.c?rev=1892646&r1=1892645&r2=1892646&view=diff
==============================================================================
--- subversion/branches/pristines-on-demand/subversion/libsvn_wc/questions.c (original)
+++ subversion/branches/pristines-on-demand/subversion/libsvn_wc/questions.c Fri Aug 27 13:52:21 2021
@@ -84,10 +84,9 @@
  *
  * If EXACT_COMPARISON is FALSE, translate VERSIONED_FILE_ABSPATH's EOL
  * style and keywords to repository-normal form according to its properties,
- * calculate checksum and compare the result with PRISTINE_STREAM.  If
- * EXACT_COMPARISON is TRUE, open pristine, translate it's EOL style and
- * keywords to working-copy form according to VERSIONED_FILE_ABSPATH's
- * properties, and compare the result with VERSIONED_FILE_ABSPATH.
+ * calculate checksum and compare the result with PRISTINE_STREAM.
+ * If EXACT_COMPARISON is TRUE, also check that VERSIONED_FILE_ABSPATH
+ * contents remains the same when retranslated according to its properties.
  *
  * HAS_PROPS should be TRUE if the file had properties when it was not
  * modified, otherwise FALSE.
@@ -131,6 +130,9 @@ compare_and_verify(svn_boolean_t *modifi
                                          !exact_comparison,
                                          scratch_pool, scratch_pool));
 
+      if (eol_style == svn_subst_eol_style_unknown)
+        return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);
+
       need_translation = svn_subst_translation_required(eol_style, eol_str,
                                                         keywords, special,
                                                         TRUE);
@@ -178,44 +180,72 @@ compare_and_verify(svn_boolean_t *modifi
 
       if (need_translation)
         {
-          if (!exact_comparison)
+          const char *pristine_eol_str;
+
+          if (eol_style == svn_subst_eol_style_native)
+            pristine_eol_str = SVN_SUBST_NATIVE_EOL_STR;
+          else
+            pristine_eol_str = eol_str;
+
+          if (exact_comparison)
             {
-              if (eol_style == svn_subst_eol_style_native)
-                eol_str = SVN_SUBST_NATIVE_EOL_STR;
-              else if (eol_style != svn_subst_eol_style_fixed
-                       && eol_style != svn_subst_eol_style_none)
-                return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL,
-                                        svn_stream_close(v_stream), NULL);
+              svn_checksum_t *working_checksum;
+              svn_checksum_t *detranslated_checksum;
+              svn_checksum_t *retranslated_checksum;
+
+              v_stream = svn_stream_checksummed2(v_stream,
+                                                 &working_checksum, NULL,
+                                                 pristine_checksum->kind, TRUE,
+                                                 scratch_pool);
+
+              v_stream = svn_subst_stream_translated(v_stream,
+                                                     pristine_eol_str, TRUE,
+                                                     keywords, FALSE,
+                                                     scratch_pool);
+              v_stream = svn_stream_checksummed2(v_stream,
+                                                 &detranslated_checksum, NULL,
+                                                 pristine_checksum->kind, TRUE,
+                                                 scratch_pool);
+
+              v_stream = svn_subst_stream_translated(v_stream, eol_str, FALSE,
+                                                     keywords, TRUE,
+                                                     scratch_pool);
+              v_stream = svn_stream_checksummed2(v_stream,
+                                                 &retranslated_checksum, NULL,
+                                                 pristine_checksum->kind, TRUE,
+                                                 scratch_pool);
+
+              err = svn_stream_copy3(v_stream, svn_stream_empty(scratch_pool),
+                                     NULL, NULL, scratch_pool);
+              /* Convert EACCESS on working copy path to WC specific error code. */
+              if (err && APR_STATUS_IS_EACCES(err->apr_err))
+                return svn_error_create(SVN_ERR_WC_PATH_ACCESS_DENIED, err, NULL);
+              else
+                SVN_ERR(err);
+
+              if (svn_checksum_match(detranslated_checksum, pristine_checksum) &&
+                  svn_checksum_match(working_checksum, retranslated_checksum))
+                {
+                  *modified_p = FALSE;
+                }
+              else
+                {
+                  *modified_p = TRUE;
+                }
 
+              return SVN_NO_ERROR;
+            }
+          else
+            {
               /* Wrap file stream to detranslate into normal form,
                * "repairing" the EOL style if it is inconsistent. */
               v_stream = svn_subst_stream_translated(v_stream,
-                                                     eol_str,
+                                                     pristine_eol_str,
                                                      TRUE /* repair */,
                                                      keywords,
                                                      FALSE /* expand */,
                                                      scratch_pool);
             }
-          else
-            {
-              svn_boolean_t same;
-              svn_stream_t *pristine_stream;
-
-              SVN_ERR(svn_wc__db_pristine_read(&pristine_stream, NULL,
-                                               db, versioned_file_abspath,
-                                               pristine_checksum,
-                                               scratch_pool, scratch_pool));
-              /* Wrap base stream to translate into working copy form, and
-               * arrange to throw an error if its EOL style is inconsistent. */
-              pristine_stream = svn_subst_stream_translated(pristine_stream,
-                                                            eol_str, FALSE,
-                                                            keywords, TRUE,
-                                                            scratch_pool);
-              SVN_ERR(svn_stream_contents_same2(&same, pristine_stream, v_stream,
-                                                scratch_pool));
-              *modified_p = (! same);
-              return SVN_NO_ERROR;
-            }
         }
     }