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 2013/01/16 18:21:48 UTC

svn commit: r1434054 - in /subversion/trunk/subversion: libsvn_wc/status.c tests/cmdline/stat_tests.py

Author: rhuijben
Date: Wed Jan 16 17:21:47 2013
New Revision: 1434054

URL: http://svn.apache.org/viewvc?rev=1434054&view=rev
Log:
Resolve a regression since 1.7.X where calling 'svn status' on a missing file
on a case-insensitive filesystem doesn't return the same information as
on its parent directory.

In <= 1.7 we always handled the root as a single target within its parent,
hiding all its siblings. This reverts us to this behavior on the only
point where we really need this for consistent output.

* subversion/libsvn_wc/status.c
  (stat_wc_dirent_case_sensitive): New function.
  (svn_wc__internal_walk_status,
   internal_status):  Use stat_wc_dirent_case_sensitive when checking the
                      target inside a working copy.

* subversion/tests/cmdline/stat_tests.py
  (status_case_changed): New test.
  (test_list): Add test.

Modified:
    subversion/trunk/subversion/libsvn_wc/status.c
    subversion/trunk/subversion/tests/cmdline/stat_tests.py

Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1434054&r1=1434053&r2=1434054&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Wed Jan 16 17:21:47 2013
@@ -2673,6 +2673,65 @@ svn_wc__get_status_editor(const svn_delt
   return SVN_NO_ERROR;
 }
 
+/* Like svn_io_stat_dirent, but works case sensitive inside working
+   copies. Before 1.8 we handled this with a selection filter inside
+   a directory */
+static svn_error_t *
+stat_wc_dirent_case_sensitive(const svn_io_dirent2_t **dirent,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+#if defined(WIN32) || defined(DARWIN)
+  svn_boolean_t is_wcroot;
+  /* We only need this code on systems with case insensitive filesystem
+     support. Enabling it unconditionally hurts performance */
+
+  /* The wcroot is "" inside the wc; handle it as not in the wc, as
+     the case of the root is indifferent to us. */
+  SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, 
+                               scratch_pool));
+
+  if (! is_wcroot)
+    {
+      apr_hash_t *dirents;
+      svn_error_t *err;
+      const char *parent_abspath;
+      const char *name;
+
+      svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool);
+
+      /* Obtain the name of the node, as stored in the directory.
+         Do this to avoid case insensitivity differences */
+
+      err = svn_io_get_dirents3(&dirents, parent_abspath, FALSE,
+                                scratch_pool, scratch_pool);
+
+      if (err
+          && (APR_STATUS_IS_ENOENT(err->apr_err)
+              || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
+        {
+          svn_error_clear(err);
+          dirents = NULL;
+        }
+      else
+        SVN_ERR(err);
+
+      *dirent = dirents ? apr_hash_get(dirents, name, APR_HASH_KEY_STRING)
+                       : NULL;
+
+      if (!*dirent)
+        *dirent = svn_io_dirent2_create(scratch_pool);
+
+      return SVN_NO_ERROR;
+    }
+#endif
+
+  return svn_error_trace(svn_io_stat_dirent(dirent, local_abspath, TRUE,
+                                            result_pool, scratch_pool));
+}
+
 svn_error_t *
 svn_wc__internal_walk_status(svn_wc__db_t *db,
                              const char *local_abspath,
@@ -2721,13 +2780,19 @@ svn_wc__internal_walk_status(svn_wc__db_
         return svn_error_trace(err);
 
       wb.externals = apr_hash_make(scratch_pool);
+
+      SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE, scratch_pool,
+                               scratch_pool));
     }
   else
-    SVN_ERR(svn_wc__db_externals_defined_below(&wb.externals, db, local_abspath,
-                                               scratch_pool, scratch_pool));
+    {
+      SVN_ERR(svn_wc__db_externals_defined_below(&wb.externals,
+                                                 db, local_abspath,
+                                                 scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE,
-                             scratch_pool, scratch_pool));
+      SVN_ERR(stat_wc_dirent_case_sensitive(&dirent, db, local_abspath,
+                                            scratch_pool, scratch_pool));
+    }
 
   if (info
       && info->kind == svn_kind_dir
@@ -2868,9 +2933,6 @@ internal_status(svn_wc_status3_t **statu
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE,
-                             scratch_pool, scratch_pool));
-
   err = svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, &conflicted,
@@ -2878,19 +2940,25 @@ internal_status(svn_wc_status3_t **statu
                              db, local_abspath,
                              scratch_pool, scratch_pool);
 
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+  if (err)
     {
+      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+        return svn_error_trace(err);
+
       svn_error_clear(err);
       node_kind = svn_kind_unknown;
       /* Ensure conflicted is always set, but don't hide tree conflicts
          on 'hidden' nodes. */
       conflicted = FALSE;
+
+      SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE,
+                                 scratch_pool, scratch_pool));
     }
-  else if (err)
-    {
-        return svn_error_trace(err);
-    }
-  else if (node_status == svn_wc__db_status_not_present
+  else
+    SVN_ERR(stat_wc_dirent_case_sensitive(&dirent, db, local_abspath,
+                                          scratch_pool, scratch_pool));
+
+  if (node_status == svn_wc__db_status_not_present
            || node_status == svn_wc__db_status_server_excluded
            || node_status == svn_wc__db_status_excluded)
     {

Modified: subversion/trunk/subversion/tests/cmdline/stat_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/stat_tests.py?rev=1434054&r1=1434053&r2=1434054&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/stat_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/stat_tests.py Wed Jan 16 17:21:47 2013
@@ -1988,6 +1988,40 @@ def status_unversioned_dir(sbox):
   svntest.actions.run_and_verify_svn2(None, [], expected_err, 0,
                                       "status", "/")
 
+def status_case_changed(sbox):
+  "status reporting on case changed nodes directly"
+
+  sbox.build(read_only = True)
+  wc_dir = sbox.wc_dir
+
+  os.rename(sbox.ospath('iota'), sbox.ospath('iOTA'))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'iOTA'         : Item(status='? '),
+  })
+  expected_status.tweak('iota', status='! ')
+
+  # First run status on the directory
+  svntest.actions.run_and_verify_unquiet_status(wc_dir,
+                                                expected_status)
+
+  # Now on the missing iota directly, which should give the same
+  # result, even on case insenstive filesystems
+  expected_status = svntest.wc.State(wc_dir, {
+    'iota'         : Item(status='! ', wc_rev=1),
+  })
+  svntest.actions.run_and_verify_unquiet_status(sbox.ospath('iota'),
+                                                expected_status)
+
+  # And on the unversioned iOTA
+  expected_status = svntest.wc.State(wc_dir, {
+    'iOTA'         : Item(status='? '),
+  })
+  svntest.actions.run_and_verify_unquiet_status(sbox.ospath('iOTA'),
+                                                expected_status)
+
+
 ########################################################################
 # Run the tests
 
@@ -2033,6 +2067,7 @@ test_list = [ None,
               modified_modulo_translation,
               status_not_present,
               status_unversioned_dir,
+              status_case_changed,
              ]
 
 if __name__ == '__main__':