You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/11/28 09:03:37 UTC

svn commit: r1414569 - in /subversion/branches/in-repo-authz: ./ subversion/include/ subversion/libsvn_wc/ subversion/tests/libsvn_repos/ subversion/tests/libsvn_subr/

Author: breser
Date: Wed Nov 28 08:03:35 2012
New Revision: 1414569

URL: http://svn.apache.org/viewvc?rev=1414569&view=rev
Log:
Sync the 'in-repo-authz' branch with recent trunk changes.
(Merged /subversion/trunk:r1414342-r1414568.)

Modified:
    subversion/branches/in-repo-authz/   (props changed)
    subversion/branches/in-repo-authz/subversion/include/svn_error_codes.h
    subversion/branches/in-repo-authz/subversion/libsvn_wc/externals.c
    subversion/branches/in-repo-authz/subversion/libsvn_wc/props.c
    subversion/branches/in-repo-authz/subversion/libsvn_wc/wc.h
    subversion/branches/in-repo-authz/subversion/tests/libsvn_repos/repos-test.c
    subversion/branches/in-repo-authz/subversion/tests/libsvn_subr/path-test.c

Propchange: subversion/branches/in-repo-authz/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1414342-1414568

Modified: subversion/branches/in-repo-authz/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/include/svn_error_codes.h?rev=1414569&r1=1414568&r2=1414569&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/include/svn_error_codes.h (original)
+++ subversion/branches/in-repo-authz/subversion/include/svn_error_codes.h Wed Nov 28 08:03:35 2012
@@ -545,6 +545,11 @@ SVN_ERROR_START
              SVN_ERR_WC_CATEGORY_START + 40,
              "Mixed-revision working copy was found but not expected")
 
+  /** @since New in 1.8 */
+  SVN_ERRDEF(SVN_ERR_WC_DUPLICATE_EXTERNALS_TARGET,
+             SVN_ERR_WC_CATEGORY_START + 41,
+             "Duplicate targets in svn:externals property")
+
   /* fs errors */
 
   SVN_ERRDEF(SVN_ERR_FS_GENERAL,

Modified: subversion/branches/in-repo-authz/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/libsvn_wc/externals.c?rev=1414569&r1=1414568&r2=1414569&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/in-repo-authz/subversion/libsvn_wc/externals.c Wed Nov 28 08:03:35 2012
@@ -164,10 +164,8 @@ svn_wc_parse_externals_description3(apr_
                                     apr_pool_t *pool)
 {
   int i;
-  unsigned int len;
   apr_array_header_t *externals = NULL;
   apr_array_header_t *lines = svn_cstring_split(desc, "\n\r", TRUE, pool);
-  apr_hash_t *duplicate_check = apr_hash_make(pool);
   const char *parent_directory_display = svn_path_is_url(parent_directory) ?
     parent_directory : svn_dirent_local_style(parent_directory, pool);
 
@@ -332,21 +330,6 @@ svn_wc_parse_externals_description3(apr_
             item->url = svn_dirent_canonicalize(item->url, pool);
         }
 
-      /* Has the same WC target path already been mentioned in this prop? */
-      len = apr_hash_count(duplicate_check);
-      apr_hash_set(duplicate_check, item->target_dir, APR_HASH_KEY_STRING, "");
-      if (len == apr_hash_count(duplicate_check))
-        {
-          /* Hashtable length is unchanged. This must be a duplicate. */
-          return svn_error_createf
-            (SVN_ERR_CLIENT_INVALID_EXTERNALS_DESCRIPTION, NULL,
-             _("Invalid %s property on '%s': "
-               "target '%s' appears more than once"),
-             SVN_PROP_EXTERNALS,
-             parent_directory_display,
-             item->target_dir);
-        }
-
       if (externals)
         APR_ARRAY_PUSH(externals, svn_wc_external_item2_t *) = item;
     }
@@ -357,6 +340,53 @@ svn_wc_parse_externals_description3(apr_
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__externals_find_target_dups(apr_array_header_t **duplicate_targets,
+                                   apr_array_header_t *externals,
+                                   apr_pool_t *pool,
+                                   apr_pool_t *scratch_pool)
+{
+  int i;
+  unsigned int len;
+  unsigned int len2;
+  const char *target;
+  apr_hash_t *targets = apr_hash_make(scratch_pool);
+  apr_hash_t *targets2 = NULL;
+  *duplicate_targets = NULL;
+
+  for (i = 0; i < externals->nelts; i++)
+    {
+      target = APR_ARRAY_IDX(externals, i,
+                                         svn_wc_external_item2_t*)->target_dir;
+      len = apr_hash_count(targets);
+      apr_hash_set(targets, target, APR_HASH_KEY_STRING, "");
+      if (len == apr_hash_count(targets))
+        {
+          /* Hashtable length is unchanged. This must be a duplicate. */
+
+          /* Collapse multiple duplicates of the same target by using a second
+           * hash layer. */
+          if (! targets2)
+            targets2 = apr_hash_make(scratch_pool);
+          len2 = apr_hash_count(targets2);
+          apr_hash_set(targets2, target, APR_HASH_KEY_STRING, "");
+          if (len2 < apr_hash_count(targets2))
+            {
+              /* The second hash list just got bigger, i.e. this target has
+               * not been counted as duplicate before. */
+              if (! *duplicate_targets)
+                {
+                  *duplicate_targets = apr_array_make(
+                                    pool, 1, sizeof(svn_wc_external_item2_t*));
+                }
+              APR_ARRAY_PUSH((*duplicate_targets), const char *) = target;
+            }
+          /* Else, this same target has already been recorded as a duplicate,
+           * don't count it again. */
+        }
+    }
+  return SVN_NO_ERROR;
+}
 
 struct edit_baton
 {

Modified: subversion/branches/in-repo-authz/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/libsvn_wc/props.c?rev=1414569&r1=1414568&r2=1414569&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/in-repo-authz/subversion/libsvn_wc/props.c Wed Nov 28 08:03:35 2012
@@ -2168,9 +2168,34 @@ svn_wc_canonicalize_svn_prop(const svn_s
              an svn:externals line.  As it happens, our parse code
              checks for this, so all we have to is invoke it --
              we're not interested in the parsed result, only in
-             whether or the parsing errored. */
-          SVN_ERR(svn_wc_parse_externals_description3
-                  (NULL, path, propval->data, FALSE, pool));
+             whether or not the parsing errored. */
+          apr_array_header_t *externals = NULL;
+          apr_array_header_t *duplicate_targets = NULL;
+          SVN_ERR(svn_wc_parse_externals_description3(&externals, path,
+                                                      propval->data, FALSE,
+                                                      /*scratch_*/pool));
+          SVN_ERR(svn_wc__externals_find_target_dups(&duplicate_targets,
+                                                     externals,
+                                                     /*scratch_*/pool,
+                                                     /*scratch_*/pool));
+          if (duplicate_targets && duplicate_targets->nelts > 0)
+            {
+              const char *more_str = "";
+              if (duplicate_targets->nelts > 1)
+                {
+                  more_str = apr_psprintf(/*scratch_*/pool,
+                               _(" (%d more duplicate targets found)"),
+                               duplicate_targets->nelts - 1);
+                }
+              return svn_error_createf(
+                SVN_ERR_WC_DUPLICATE_EXTERNALS_TARGET, NULL,
+                _("Invalid %s property on '%s': "
+                  "target '%s' appears more than once%s"),
+                SVN_PROP_EXTERNALS,
+                svn_dirent_local_style(path, pool),
+                APR_ARRAY_IDX(duplicate_targets, 0, const char*),
+                more_str);
+            }
         }
     }
   else if (strcmp(propname, SVN_PROP_KEYWORDS) == 0)

Modified: subversion/branches/in-repo-authz/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/libsvn_wc/wc.h?rev=1414569&r1=1414568&r2=1414569&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/in-repo-authz/subversion/libsvn_wc/wc.h Wed Nov 28 08:03:35 2012
@@ -755,6 +755,16 @@ svn_wc__fetch_base_func(const char **fil
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool);
 
+/* Find duplicate targets in *EXTERNALS, a list of svn_wc_external_item2_t*
+ * elements, and store each target string in *DUPLICATE_TARGETS as const
+ * char * elements. *DUPLICATE_TARGETS will be NULL if no duplicates were
+ * found. */
+svn_error_t *
+svn_wc__externals_find_target_dups(apr_array_header_t **duplicate_targets,
+                                   apr_array_header_t *externals,
+                                   apr_pool_t *pool,
+                                   apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/in-repo-authz/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/tests/libsvn_repos/repos-test.c?rev=1414569&r1=1414568&r2=1414569&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/in-repo-authz/subversion/tests/libsvn_repos/repos-test.c Wed Nov 28 08:03:35 2012
@@ -49,6 +49,20 @@
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #endif
 
+/* Compare strings, like strcmp but either or both may be NULL which
+ * compares equal to NULL and not equal to any non-NULL string. */
+static int
+strcmp_null(const char *s1, const char *s2)
+{
+  if (s1 && s2)
+    return strcmp(s1, s2);
+  else if (s1 || s2)
+    return 1;
+  else
+    return 0;
+}
+
+
 
 static svn_error_t *
 dir_deltas(const svn_test_opts_t *opts,
@@ -1739,7 +1753,9 @@ nls_receiver(svn_location_segment_t *seg
                              "Got unexpected location segment: %s",
                              format_segment(segment, pool));
 
-  if (expected_segment->range_start != segment->range_start)
+  if (expected_segment->range_start != segment->range_start
+      || expected_segment->range_end != segment->range_end
+      || strcmp_null(expected_segment->path, segment->path) != 0)
     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                              "Location segments differ\n"
                              "   Expected location segment: %s\n"
@@ -1950,7 +1966,7 @@ node_location_segments(const svn_test_op
         { 6, 6, "A/D2/G" },
         { 5, 5, NULL },
         { 3, 4, "A/D2/G" },
-        { 1, 2, "A/D2/G" },
+        { 1, 2, "A/D/G" },
         { 0 }
       };
     SVN_ERR(check_location_segments(repos, "A/D/G",
@@ -1965,7 +1981,7 @@ node_location_segments(const svn_test_op
     svn_location_segment_t expected_segments[] =
       {
         { 3, 3, "A/D2/G" },
-        { 2, 2, "A/D2/G" },
+        { 2, 2, "A/D/G" },
         { 0 }
       };
     SVN_ERR(check_location_segments(repos, "A/D/G",

Modified: subversion/branches/in-repo-authz/subversion/tests/libsvn_subr/path-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/in-repo-authz/subversion/tests/libsvn_subr/path-test.c?rev=1414569&r1=1414568&r2=1414569&view=diff
==============================================================================
--- subversion/branches/in-repo-authz/subversion/tests/libsvn_subr/path-test.c (original)
+++ subversion/branches/in-repo-authz/subversion/tests/libsvn_subr/path-test.c Wed Nov 28 08:03:35 2012
@@ -1202,7 +1202,6 @@ test_path_splitext(apr_pool_t *pool)
     const char *path;
     const char *path_root;
     const char *path_ext;
-    svn_boolean_t result;
   } tests[] = {
     { "no-ext",                    "no-ext",                 "" },
     { "test-file.py",              "test-file.",             "py" },