subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1544906 - in /subversion/trunk/subversion: include/ include/private/ libsvn_repos/ libsvn_subr/ svnadmin/ tests/cmdline/ tests/cmdline/svnadmin_tests_data/
Date Sun, 24 Nov 2013 04:07:24 GMT
Author: brane
Date: Sun Nov 24 04:07:24 2013
New Revision: 1544906

URL: http://svn.apache.org/r1544906
Log:
Added an option to 'svnadmin verify' to check Unicode normalisation of
repository paths, and collisions of names within the same directory
that differ only in character representation.

* subversion/include/svn_repos.h (svn_repos_notify_warning_t):
   New constants 'svn_repos_notify_warning_denormalized_name'
   and 'svn_repos_notify_warning_name_collision'.
  (svn_repos_verify_fs3): Added 'check_ucs_norm' argument and
   updated the docstring.
  (svn_repos_verify_fs2): Updated the docstring.

* subversion/libsvn_repos/dump.c (struct edit_baton):
   New member 'check_ucs_norm'.
  (struct dir_baton): New member 'check_name_collision'.
  (make_dir_baton): Initialise 'check_name_collision'.
  (check_ucs_normalization): New private function.
  (add_directory, add_file): Set 'check_name_collision' and call
   check_ucs_normalization if a new entry appeared in the directory.
  (get_dump_editor): New argument 'check_ucs_norm'; used to initialise
   the associated field in 'struct edit_baton'.
  (svn_repos_dump_fs3): Update call to get_dump_editor.
  (struct check_name_baton) New.
  (check_name_collision) New hash iterator.
  (verify_close_directory): Optionally call check_name_collision.
  (verify_one_revision): New argument 'check_ucs_norm'.
   Pass it to get_dump_editor.
  (svn_repos_verify_fs3): Update signature and pass 'check_ucs_norm'
   to verify_one_revision.

* subversion/libsvn_repos/deprecated.c (svn_repos_verify_fs2):
   Updated the call to svn_repos_verify_fs3.

* subversion/include/private/svn_utf_private.h (svn_utf__normalize):
   New function. Normalizes a string to Unicode NFC.
* subversion/libsvn_subr/utf8proc.c (svn_utf__normalize): Implement.

* subversion/svnadmin/svnadmin.c (svnadmin__cmdline_options_t, options_table):
   New option 'svnadmin__check_ucs_normalization'.
  (cmd_table): Add 'svnadmin__check_ucs_normalization' to "verify".
  (struct svnadmin_opt_state): New member 'check_ucs_norm'.
  (sub_main): Parse new option to 'check_ucs_norm'.

* subversion/tests/cmdline/svnadmin_tests.py (verify_denormalized_names):
   New test case; runs 'svnadmin verify' with normalisation check enabled.
  (test_list): Enable verify_denormalized_names.
* subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump:
   New dumpfile; data for svnadmin_tests.verify_denormalized_names.

Added:
    subversion/trunk/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
  (with props)
Modified:
    subversion/trunk/subversion/include/private/svn_utf_private.h
    subversion/trunk/subversion/include/svn_repos.h
    subversion/trunk/subversion/libsvn_repos/deprecated.c
    subversion/trunk/subversion/libsvn_repos/dump.c
    subversion/trunk/subversion/libsvn_subr/utf8proc.c
    subversion/trunk/subversion/svnadmin/svnadmin.c
    subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py

Modified: subversion/trunk/subversion/include/private/svn_utf_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_utf_private.h?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_utf_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_utf_private.h Sun Nov 24 04:07:24 2013
@@ -134,6 +134,22 @@ svn_utf__normcmp(int *result,
                  const char *str2, apr_size_t len2,
                  svn_membuf_t *buf1, svn_membuf_t *buf2);
 
+/* Normalize the UTF-8 string STR to form C, using BUF for temporary
+ * storage. If LEN is SVN_UTF__UNKNOWN_LENGTH, assume STR is
+ * null-terminated; otherwise, consider the string only up to the
+ * given length.
+ *
+ * Return the normalized string in *RESULT, which shares storage with
+ * BUF and is valid only until the next time BUF is modified.
+ *
+ * A returned error may indicate that STRING contains invalid UTF-8 or
+ * invalid Unicode codepoints.
+ */
+svn_error_t*
+svn_utf__normalize(const char **result,
+                   const char *str, apr_size_t len,
+                   svn_membuf_t *buf);
+
 /* Check if STRING is a valid, NFC-normalized UTF-8 string.  Note that
  * a FALSE return value may indicate that STRING is not valid UTF-8 at
  * all.

Modified: subversion/trunk/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_repos.h?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_repos.h (original)
+++ subversion/trunk/subversion/include/svn_repos.h Sun Nov 24 04:07:24 2013
@@ -284,8 +284,24 @@ typedef enum svn_repos_notify_warning_t
    * @see svn_fs.h:"Directory entry names and directory paths" */
   /* ### TODO(doxygen): make that a proper doxygen link */
   /* See svn_fs__path_valid(). */
-  svn_repos_notify_warning_invalid_fspath
+  svn_repos_notify_warning_invalid_fspath,
 
+  /**
+   * Found a denormalized name. Reported when the name of a directoy
+   * entry is not normalized to Unicode Normalization Form C.
+   *
+   * @since New in 1.9.
+   */
+  svn_repos_notify_warning_denormalized_name,
+
+  /**
+   * Detected a name collision. Reported when the names of two or more
+   * entries in the same directory differ only in character
+   * representation (normalization), but are otherwise identical.
+   *
+   * @since New in 1.9.
+   */
+  svn_repos_notify_warning_name_collision
 } svn_repos_notify_warning_t;
 
 /**
@@ -2659,6 +2675,12 @@ svn_repos_info_format(int *repos_format,
  * not notified. Finally, return an error if there were any failures during
  * verification, or SVN_NO_ERROR if there were no failures.
  *
+ * If @a check_ucs_norm is @c TRUE, verify that all path names in the
+ * repository are normaized to Unicode Normalization Form C, and
+ * report any name collisions within the same directory where the
+ * names differ only in character representation, but are otherwise
+ * identical.
+ *
  * @since New in 1.9.
  */
 svn_error_t *
@@ -2666,6 +2688,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
                      svn_revnum_t start_rev,
                      svn_revnum_t end_rev,
                      svn_boolean_t keep_going,
+                     svn_boolean_t check_ucs_norm,
                      svn_repos_notify_func_t notify_func,
                      void *notify_baton,
                      svn_cancel_func_t cancel,
@@ -2673,7 +2696,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
                      apr_pool_t *scratch_pool);
 
 /**
- * Like svn_repos_verify_fs3(), but with @a keep_going set to @c FALSE.
+ * Like svn_repos_verify_fs3(), but with @a keep_going and
+ * @a check_ucs_norm set to @c FALSE.
  *
  * @since New in 1.7.
  * @deprecated Provided for backward compatibility with the 1.8 API.

Modified: subversion/trunk/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/deprecated.c?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_repos/deprecated.c Sun Nov 24 04:07:24 2013
@@ -763,6 +763,7 @@ svn_repos_verify_fs2(svn_repos_t *repos,
                                               start_rev,
                                               end_rev,
                                               FALSE,
+                                              FALSE,
                                               notify_func,
                                               notify_baton,
                                               cancel_func,

Modified: subversion/trunk/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/dump.c?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/dump.c (original)
+++ subversion/trunk/subversion/libsvn_repos/dump.c Sun Nov 24 04:07:24 2013
@@ -38,6 +38,7 @@
 
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_fs_private.h"
+#include "private/svn_utf_private.h"
 #include "private/svn_cache.h"
 
 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
@@ -380,6 +381,9 @@ struct edit_baton
   /* True if this "dump" is in fact a verify. */
   svn_boolean_t verify;
 
+  /* True if checking UCS normalization during a verify. */
+  svn_boolean_t check_ucs_norm;
+
   /* The first revision dumped in this dumpstream. */
   svn_revnum_t oldest_dumped_rev;
 
@@ -434,6 +438,12 @@ struct dir_baton
      really, they're all within this directory.) */
   apr_hash_t *deleted_entries;
 
+  /* A flag indicating that new entries have been added to this
+     directory in this revision. Used to optimize detection of UCS
+     representation collisions; we will only check for that in
+     revisions where new names appear in the directory. */
+  svn_boolean_t check_name_collision;
+
   /* pool to be used for deleting the hash items */
   apr_pool_t *pool;
 };
@@ -486,6 +496,7 @@ make_dir_baton(const char *path,
   new_db->added = added;
   new_db->written_out = FALSE;
   new_db->deleted_entries = apr_hash_make(pool);
+  new_db->check_name_collision = FALSE;
   new_db->pool = pool;
 
   return new_db;
@@ -581,6 +592,39 @@ node_must_not_exist(struct edit_baton *e
   return SVN_NO_ERROR;
 }
 
+
+static svn_error_t *
+check_ucs_normalization(const char *path,
+                        svn_node_kind_t kind,
+                        svn_repos_notify_func_t notify_func,
+                        void *notify_baton,
+                        apr_pool_t *scratch_pool)
+{
+  const char *const basename = svn_relpath_basename(path, scratch_pool);
+  if (!svn_utf__is_normalized(basename, scratch_pool))
+    {
+      svn_repos_notify_t *const notify =
+        svn_repos_notify_create(svn_repos_notify_warning, scratch_pool);
+      notify->warning = svn_repos_notify_warning_denormalized_name;
+      switch (kind)
+        {
+        case svn_node_dir:
+          notify->warning_str = apr_psprintf(
+              scratch_pool, _("Denormalized directory name '%s'"), path);
+          break;
+        case svn_node_file:
+          notify->warning_str = apr_psprintf(
+              scratch_pool, _("Denormalized file name '%s'"), path);
+          break;
+        default:
+          notify->warning_str = apr_psprintf(
+              scratch_pool, _("Denormalized entry name '%s'"), path);
+        }
+      notify_func(notify_baton, notify, scratch_pool);
+    }
+  return SVN_NO_ERROR;
+}
+
 /* This helper is the main "meat" of the editor -- it does all the
    work of writing a node record.
 
@@ -1116,6 +1160,16 @@ add_directory(const char *path,
     /* Delete the path, it's now been dumped. */
     svn_hash_sets(pb->deleted_entries, path, NULL);
 
+  /* Check for UCS normalization and name clashes, but only if this is
+     actually a new name in the parent, not a replacement. */
+  if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
+    {
+      pb->check_name_collision = TRUE;
+      SVN_ERR(check_ucs_normalization(
+                  path, svn_node_file,
+                  eb->notify_func, eb->notify_baton, pool));
+    }
+
   new_db->written_out = TRUE;
 
   *child_baton = new_db;
@@ -1215,6 +1269,16 @@ add_file(const char *path,
                     is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
                     pool));
 
+  /* Check for UCS normalization and name clashes, but only if this is
+     actually a new name in the parent, not a replacement. */
+  if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
+    {
+      pb->check_name_collision = TRUE;
+      SVN_ERR(check_ucs_normalization(
+                  path, svn_node_file,
+                  eb->notify_func, eb->notify_baton, pool));
+    }
+
   if (val)
     /* delete the path, it's now been dumped. */
     svn_hash_sets(pb->deleted_entries, path, NULL);
@@ -1382,6 +1446,7 @@ get_dump_editor(const svn_delta_editor_t
                 svn_revnum_t oldest_dumped_rev,
                 svn_boolean_t use_deltas,
                 svn_boolean_t verify,
+                svn_boolean_t check_ucs_norm,
                 svn_cache__t *verified_dirents_cache,
                 apr_pool_t *pool)
 {
@@ -1405,6 +1470,7 @@ get_dump_editor(const svn_delta_editor_t
   eb->current_rev = to_rev;
   eb->use_deltas = use_deltas;
   eb->verify = verify;
+  eb->check_ucs_norm = check_ucs_norm;
   eb->found_old_reference = found_old_reference;
   eb->found_old_mergeinfo = found_old_mergeinfo;
   eb->verified_dirents_cache = verified_dirents_cache;
@@ -1612,7 +1678,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
                               "", stream, &found_old_reference,
                               &found_old_mergeinfo, NULL,
                               notify_func, notify_baton,
-                              start_rev, use_deltas_for_rev, FALSE,
+                              start_rev, use_deltas_for_rev, FALSE, FALSE,
                               NULL, subpool));
 
       /* Drive the editor in one way or another. */
@@ -1790,9 +1856,57 @@ verify_directory_entry(void *baton, cons
   return SVN_NO_ERROR;
 }
 
+/* Baton used by the check_name_collision hash iterator. */
+struct check_name_baton
+{
+  struct dir_baton *dir_baton;
+  apr_hash_t *normalized;
+  svn_membuf_t buffer;
+};
+
+/* Scan the directory and report all entry names that differ only in
+   Unicode character representaiton. */
 static svn_error_t *
-verify_close_directory(void *dir_baton,
-                apr_pool_t *pool)
+check_name_collision(void *baton, const void *key, apr_ssize_t klen,
+                     void *val, apr_pool_t *pool)
+{
+  static const char unique[] = "unique";
+  static const char collision[] = "collision";
+
+  struct check_name_baton *const check_baton = baton;
+  const char *name;
+  const char *found;
+
+  SVN_ERR(svn_utf__normalize(&name, key, klen, &check_baton->buffer));
+
+  found = svn_hash_gets(check_baton->normalized, name);
+  if (!found)
+    svn_hash_sets(check_baton->normalized, name, unique);
+  else if (found == collision)
+    /* Skip already reported collision */;
+  else
+    {
+      struct dir_baton *const db = check_baton->dir_baton;
+      struct edit_baton *const eb = db->edit_baton;
+      svn_repos_notify_t *notify;
+      const char* normpath;
+
+      svn_hash_sets(check_baton->normalized, name, collision);
+      SVN_ERR(svn_utf__normalize(
+                  &normpath, svn_relpath_join(db->path, name, pool),
+                  SVN_UTF__UNKNOWN_LENGTH, &check_baton->buffer));
+      notify = svn_repos_notify_create(svn_repos_notify_warning, pool);
+      notify->warning = svn_repos_notify_warning_name_collision;
+      notify->warning_str = apr_psprintf(
+          pool, _("Duplicate representation of path '%s'"), normpath);
+      eb->notify_func(eb->notify_baton, notify, pool);
+    }
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+verify_close_directory(void *dir_baton, apr_pool_t *pool)
 {
   struct dir_baton *db = dir_baton;
   apr_hash_t *dirents;
@@ -1800,6 +1914,17 @@ verify_close_directory(void *dir_baton,
                              db->path, pool));
   SVN_ERR(svn_iter_apr_hash(NULL, dirents, verify_directory_entry,
                             dir_baton, pool));
+
+  if (db->check_name_collision)
+    {
+      struct check_name_baton check_baton;
+      check_baton.dir_baton = db;
+      check_baton.normalized = apr_hash_make(pool);
+      svn_membuf__create(&check_baton.buffer, 0, pool);
+      SVN_ERR(svn_iter_apr_hash(NULL, dirents, check_name_collision,
+                                &check_baton, pool));
+    }
+
   return close_directory(dir_baton, pool);
 }
 
@@ -1828,6 +1953,7 @@ verify_one_revision(svn_fs_t *fs,
                     svn_repos_notify_func_t notify_func,
                     void *notify_baton,
                     svn_revnum_t start_rev,
+                    svn_boolean_t check_ucs_norm,
                     svn_cancel_func_t cancel_func,
                     void *cancel_baton,
                     svn_cache__t *verified_dirents_cache,
@@ -1849,6 +1975,7 @@ verify_one_revision(svn_fs_t *fs,
                           notify_func, notify_baton,
                           start_rev,
                           FALSE, TRUE, /* use_deltas, verify */
+                          check_ucs_norm,
                           verified_dirents_cache,
                           scratch_pool));
   SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
@@ -1926,6 +2053,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
                      svn_revnum_t start_rev,
                      svn_revnum_t end_rev,
                      svn_boolean_t keep_going,
+                     svn_boolean_t check_ucs_norm,
                      svn_repos_notify_func_t notify_func,
                      void *notify_baton,
                      svn_cancel_func_t cancel_func,
@@ -2021,7 +2149,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
 
       /* Wrapper function to catch the possible errors. */
       err = verify_one_revision(fs, rev, notify_func, notify_baton,
-                                start_rev, cancel_func, cancel_baton,
+                                start_rev, check_ucs_norm,
+                                cancel_func, cancel_baton,
                                 verified_dirents_cache, iterpool);
 
       if (err)

Modified: subversion/trunk/subversion/libsvn_subr/utf8proc.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/utf8proc.c?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/utf8proc.c (original)
+++ subversion/trunk/subversion/libsvn_subr/utf8proc.c Sun Nov 24 04:07:24 2013
@@ -155,7 +155,6 @@ ucs4cmp(const apr_int32_t *bufa, apr_siz
   return (lena == lenb ? 0 : (lena < lenb ? -1 : 1));
 }
 
-
 svn_error_t *
 svn_utf__normcmp(int *result,
                  const char *str1, apr_size_t len1,
@@ -182,6 +181,16 @@ svn_utf__normcmp(int *result,
   return SVN_NO_ERROR;
 }
 
+svn_error_t*
+svn_utf__normalize(const char **result,
+                   const char *str, apr_size_t len,
+                   svn_membuf_t *buf)
+{
+  apr_size_t result_length;
+  SVN_ERR(normalize_cstring(&result_length, str, len, buf));
+  *result = (const char*)(buf->data);
+  return SVN_NO_ERROR;
+}
 
 /* Decode a single UCS-4 code point to UTF-8, appending the result to BUFFER.
  * Assume BUFFER is already filled to *LENGTH and return the new size there.

Modified: subversion/trunk/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnadmin/svnadmin.c?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/svnadmin/svnadmin.c (original)
+++ subversion/trunk/subversion/svnadmin/svnadmin.c Sun Nov 24 04:07:24 2013
@@ -197,7 +197,8 @@ enum svnadmin__cmdline_options_t
     svnadmin__pre_1_4_compatible,
     svnadmin__pre_1_5_compatible,
     svnadmin__pre_1_6_compatible,
-    svnadmin__compatible_version
+    svnadmin__compatible_version,
+    svnadmin__check_ucs_normalization
   };
 
 /* Option codes and descriptions.
@@ -302,6 +303,12 @@ static const apr_getopt_option_t options
 
     {"file", 'F', 1, N_("read repository paths from file ARG")},
 
+    {"check-ucs-normalization", svnadmin__check_ucs_normalization, 0,
+     N_("report path names that are not normalized to UCS\n"
+        "                             Normalization Form C, and and any names within\n"
+        "                             the same directory that differ only in character\n"
+        "                             representation, but are otherwise identical")},
+
     {NULL}
   };
 
@@ -494,7 +501,8 @@ static const svn_opt_subcommand_desc2_t 
   {"verify", subcommand_verify, {0}, N_
    ("usage: svnadmin verify REPOS_PATH\n\n"
     "Verify the data stored in the repository.\n"),
-  {'t', 'r', 'q', svnadmin__keep_going, 'M'} },
+   {'t', 'r', 'q', svnadmin__keep_going, 'M',
+    svnadmin__check_ucs_normalization} },
 
   { NULL, NULL, {0}, NULL, {0} }
 };
@@ -523,6 +531,7 @@ struct svnadmin_opt_state
   svn_boolean_t bypass_hooks;                       /* --bypass-hooks */
   svn_boolean_t wait;                               /* --wait */
   svn_boolean_t keep_going;                         /* --keep-going */
+  svn_boolean_t check_ucs_norm;                     /* --check-ucs-normalization */
   svn_boolean_t bypass_prop_validation;             /* --bypass-prop-validation */
   enum svn_repos_load_uuid uuid_action;             /* --ignore-uuid,
                                                        --force-uuid */
@@ -1689,6 +1698,7 @@ subcommand_verify(apr_getopt_t *os, void
 
   return svn_error_trace(svn_repos_verify_fs3(repos, lower, upper,
                                               opt_state->keep_going,
+                                              opt_state->check_ucs_norm,
                                               !opt_state->quiet
                                               ? repos_notify_handler : NULL,
                                               progress_stream, check_cancel,
@@ -2308,6 +2318,9 @@ sub_main(int *exit_code, int argc, const
       case svnadmin__keep_going:
         opt_state.keep_going = TRUE;
         break;
+      case svnadmin__check_ucs_normalization:
+        opt_state.check_ucs_norm = TRUE;
+        break;
       case svnadmin__fs_type:
         SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.fs_type, opt_arg, pool));
         break;

Modified: subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py?rev=1544906&r1=1544905&r2=1544906&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py Sun Nov 24 04:07:24 2013
@@ -2037,6 +2037,44 @@ def verify_invalid_path_changes(sbox):
                                    None, errput, None, "svnadmin: E165011:.*"):
     raise svntest.Failure
 
+
+def verify_denormalized_names(sbox):
+  "detect denormalized names and name collisions"
+
+  sbox.build(create_wc = False)
+  svntest.main.safe_rmtree(sbox.repo_dir, True)
+  svntest.main.create_repos(sbox.repo_dir)
+
+  dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]),
+                                   'svnadmin_tests_data',
+                                   'normalization_check.dump')
+  load_dumpstream(sbox, open(dumpfile_location).read())
+
+  exit_code, output, errput = svntest.main.run_svnadmin(
+    "verify", "--check-ucs-normalization", sbox.repo_dir)
+
+  exp_out = svntest.verify.RegexListOutput([
+    ".*Verifying repository metadata",
+    ".*Verified revision 0.",
+                                       # A/{Eacute}
+    "WARNING .*: Denormalized file name 'A/.*'",
+                                       # A/{icircumflex}{odiaeresis}ta
+    "WARNING .*: Denormalized file name 'A/.*ta'",
+    ".*Verified revision 1.",
+    ".*Verified revision 2.",
+    ".*Verified revision 3.",
+                                       # A/{Eacute}/{aring}lpha
+    "WARNING .*: Denormalized file name 'A/.*/.*lpha'",
+    "WARNING .*: Duplicate representation of path 'A/.*/.*lpha'",
+    ".*Verified revision 4.",
+    ".*Verified revision 5."])
+
+  if svntest.verify.verify_outputs(
+      "Unexpected error while running 'svnadmin verify'.",
+      output, errput, exp_out, None):
+    raise svntest.Failure
+
+
 ########################################################################
 # Run the tests
 
@@ -2075,6 +2113,7 @@ test_list = [ None,
               recover_old,
               verify_keep_going,
               verify_invalid_path_changes,
+              verify_denormalized_names,
              ]
 
 if __name__ == '__main__':

Added: subversion/trunk/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump?rev=1544906&view=auto
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
(added)
+++ subversion/trunk/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
[UTF-8] Sun Nov 24 04:07:24 2013
@@ -0,0 +1,191 @@
+SVN-fs-dump-format-version: 2
+
+UUID: bf695de5-cd61-4024-8cb3-a12d299c7c62
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2013-11-24T02:29:36.942478Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 124
+Content-length: 124
+
+K 10
+svn:author
+V 5
+brane
+K 8
+svn:date
+V 27
+2013-11-24T02:34:17.982927Z
+K 7
+svn:log
+V 24
+Denormalized tree import
+PROPS-END
+
+Node-path: A
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: A/É
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: A/É/ålpha
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: A/îöta
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 126
+Content-length: 126
+
+K 10
+svn:author
+V 5
+brane
+K 8
+svn:date
+V 27
+2013-11-24T02:34:39.316466Z
+K 7
+svn:log
+V 26
+Modified denormalized file
+PROPS-END
+
+Node-path: A/îöta
+Node-kind: file
+Node-action: change
+Text-content-length: 9
+Text-content-md5: d2508118d0d39e198d1129d87d692d59
+Text-content-sha1: e2fb5f2139d086ded2cb600d5a91a196e76bf020
+Content-length: 9
+
+modified
+
+
+Revision-number: 3
+Prop-content-length: 124
+Content-length: 124
+
+K 10
+svn:author
+V 5
+brane
+K 8
+svn:date
+V 27
+2013-11-24T02:35:09.976189Z
+K 7
+svn:log
+V 24
+Modified normalized file
+PROPS-END
+
+Node-path: A/É/ålpha
+Node-kind: file
+Node-action: change
+Text-content-length: 9
+Text-content-md5: d2508118d0d39e198d1129d87d692d59
+Text-content-sha1: e2fb5f2139d086ded2cb600d5a91a196e76bf020
+Content-length: 9
+
+modified
+
+
+Revision-number: 4
+Prop-content-length: 122
+Content-length: 122
+
+K 10
+svn:author
+V 5
+brane
+K 8
+svn:date
+V 27
+2013-11-24T02:36:11.674695Z
+K 7
+svn:log
+V 22
+Created name collision
+PROPS-END
+
+Node-path: A/É/ålpha
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 5
+Prop-content-length: 123
+Content-length: 123
+
+K 10
+svn:author
+V 5
+brane
+K 8
+svn:date
+V 27
+2013-11-24T02:36:52.182891Z
+K 7
+svn:log
+V 23
+Modified colliding file
+PROPS-END
+
+Node-path: A/É/ålpha
+Node-kind: file
+Node-action: change
+Text-content-length: 9
+Text-content-md5: d2508118d0d39e198d1129d87d692d59
+Text-content-sha1: e2fb5f2139d086ded2cb600d5a91a196e76bf020
+Content-length: 9
+
+modified
+
+

Propchange: subversion/trunk/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
------------------------------------------------------------------------------
    svn:mime-type = text/plain; charset=UTF-8



Mime
View raw message