You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2016/01/13 17:19:50 UTC

svn commit: r1724448 - in /subversion/trunk/subversion: libsvn_wc/update_editor.c tests/cmdline/authz_tests.py

Author: rhuijben
Date: Wed Jan 13 16:19:50 2016
New Revision: 1724448

URL: http://svn.apache.org/viewvc?rev=1724448&view=rev
Log:
Resolve a regression in our auth handling on update, which it appears I
introduced somewhere during the WC-NG work for Subversion 1.7.

Before this patch directories that are hidden by a change in authz settings
cause a skip caused by unversioned working copy message. After this patch
the nodes are properly removed from the working copy, introducing tree
conflicts if there are local changes.

* subversion/libsvn_wc/update_editor.c
  (absent_node): Properly hide newly server excluded nodes.

* subversion/tests/cmdline/authz_tests.py
  (remove_access_after_commit): New test
  (test_list): Add new test.

Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c
    subversion/trunk/subversion/tests/cmdline/authz_tests.py

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1724448&r1=1724447&r2=1724448&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Wed Jan 13 16:19:50 2016
@@ -2883,10 +2883,7 @@ absent_node(const char *path,
   if (pb->skip_this)
     return SVN_NO_ERROR;
 
-  SVN_ERR(mark_directory_edited(pb, scratch_pool));
-
   local_abspath = svn_dirent_join(pb->local_abspath, name, scratch_pool);
-
   /* If an item by this name is scheduled for addition that's a
      genuine tree-conflict.  */
   err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
@@ -2906,6 +2903,10 @@ absent_node(const char *path,
       kind = svn_node_unknown;
     }
 
+  if (status != svn_wc__db_status_server_excluded)
+    SVN_ERR(mark_directory_edited(pb, scratch_pool));
+  /* Else fall through as we should update the revision anyway */
+
   if (status == svn_wc__db_status_normal)
     {
       svn_boolean_t wcroot;
@@ -2929,31 +2930,53 @@ absent_node(const char *path,
         }
       else
         {
-          /* The server asks us to replace a file external
-             (Existing BASE node; not reported by the working copy crawler or
-              there would have been a delete_entry() call.
-
-             There is no way we can store this state in the working copy as
-             the BASE layer is already filled.
-
-             We could error out, but that is not helping anybody; the user is not
-             even seeing with what the file external would be replaced, so let's
-             report a skip and continue the update.
-           */
+          svn_boolean_t file_external;
+          svn_revnum_t revnum;
 
-          if (eb->notify_func)
+          SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &revnum, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL,
+                                           &file_external,
+                                           eb->db, local_abspath,
+                                           scratch_pool, scratch_pool));
+
+          if (file_external)
             {
-              svn_wc_notify_t *notify;
-              notify = svn_wc_create_notify(
+              /* The server asks us to replace a file external
+                 (Existing BASE node; not reported by the working copy crawler
+                  or there would have been a delete_entry() call.
+
+                 There is no way we can store this state in the working copy as
+                 the BASE layer is already filled.
+                 We could error out, but that is not helping anybody; the user is not
+                 even seeing with what the file external would be replaced, so let's
+                 report a skip and continue the update.
+               */
+
+              if (eb->notify_func)
+                {
+                  svn_wc_notify_t *notify;
+                  notify = svn_wc_create_notify(
                                     local_abspath,
                                     svn_wc_notify_update_skip_obstruction,
                                     scratch_pool);
 
-              eb->notify_func(eb->notify_baton, notify, scratch_pool);
+                  eb->notify_func(eb->notify_baton, notify, scratch_pool);
+                }
+
+              svn_pool_destroy(scratch_pool);
+              return SVN_NO_ERROR;
             }
+          else
+            {
+              /* We have a normal local node that will now be hidden for the
+                 user. Let's try to delete what is there. This may introduce
+                 tree conflicts if there are local changes */
+              SVN_ERR(delete_entry(path, revnum, pb, scratch_pool));
 
-          svn_pool_destroy(scratch_pool);
-          return SVN_NO_ERROR;
+              /* delete_entry() promises that BASE is empty after the operation,
+                 so we can just fall through now */
+            }
         }
     }
   else if (status == svn_wc__db_status_not_present

Modified: subversion/trunk/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/authz_tests.py?rev=1724448&r1=1724447&r2=1724448&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/authz_tests.py Wed Jan 13 16:19:50 2016
@@ -1610,6 +1610,57 @@ def authz_log_censor_revprops(sbox):
     args=['--with-revprop', 'svn:author', '--with-revprop', 's',
           '-r1', sbox.repo_url])
 
+@Skip(svntest.main.is_ra_type_file)
+def remove_access_after_commit(sbox):
+  "remove a subdir with authz file"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.main.write_restrictive_svnserve_conf(sbox.repo_dir)
+  svntest.main.write_authz_file(sbox, { "/"      : "*=rw"})
+
+  # Modification in subtree
+  sbox.simple_append('A/B/E/alpha', 'appended\n')
+  sbox.simple_append('A/D/G/rho', 'appended\n')
+  sbox.simple_commit()
+
+  svntest.main.write_authz_file(sbox, { "/"      : "*=rw",
+                                        "/A/B"   : "*=",
+                                        "/A/D"   : "*="})
+
+  # Local modification
+  sbox.simple_append('A/D/G/pi', 'appended\n')
+
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B'  : Item(status='D '),
+    'A/D'  : Item(status='  ', treeconflict='C'),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/D/G/rho',
+                      contents="This is the file 'rho'.\nappended\n")
+  expected_disk.tweak('A/D/G/pi',
+                      contents="This is the file 'pi'.\nappended\n")
+  expected_disk.remove('A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
+                       'A/B/F', 'A/B/lambda')
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+
+  expected_status.tweak('A/D', status='R ',treeconflict='C', )
+  expected_status.tweak('A/D', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
+                        'A/D/H', 'A/D/H/omega', 'A/D/H/chi', 'A/D/H/psi',
+                        'A/D/gamma', copied='+', wc_rev='-')
+  expected_status.tweak('A/D/G/pi', status='M ')
+  expected_status.remove('A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F',
+                         'A/B/lambda')
+
+  # And expect a mixed rev copy
+  expected_status.tweak('A/D/G/rho', status='A ', entry_status='  ')
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        [], True)
+
 
 ########################################################################
 # Run the tests
@@ -1646,6 +1697,7 @@ test_list = [ None,
               log_diff_dontdothat,
               authz_file_external_to_authz,
               authz_log_censor_revprops,
+              remove_access_after_commit,
              ]
 serial_only = True