subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ne...@apache.org
Subject svn commit: r1414442 - in /subversion/trunk/subversion: include/svn_error_codes.h libsvn_wc/externals.c libsvn_wc/props.c libsvn_wc/wc.h
Date Tue, 27 Nov 2012 22:29:25 GMT
Author: neels
Date: Tue Nov 27 22:29:23 2012
New Revision: 1414442

URL: http://svn.apache.org/viewvc?rev=1414442&view=rev
Log:
Change implementation of issue #4227: move the svn:externals duplication check
from svn_wc_parse_externals_description3() to svn_wc_canonicalize_svn_prop().
Thus, show duplication errors only during propset/propedit.

TODO: print warnings about duplicate targets during co/up/merge.

* subversion/include/svn_error_codes.h
  (SVN_ERR_WC_DUPLICATE_EXTERNALS_TARGET): New error code.

* subversion/libsvn_wc/externals.c
  (svn_wc_parse_externals_description3): Remove dup check.
  (svn_wc__externals_find_target_dups): New function.

* subversion/libsvn_wc/wc.h
  (svn_wc__externals_find_target_dups): Declare new function.

* subversion/libsvn_wc/props.c
  (svn_wc_canonicalize_svn_prop): 
   Check against duplicate externals targets. Add missing "not" in comment.

Modified:
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/libsvn_wc/externals.c
    subversion/trunk/subversion/libsvn_wc/props.c
    subversion/trunk/subversion/libsvn_wc/wc.h

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1414442&r1=1414441&r2=1414442&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Tue Nov 27 22:29:23 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/trunk/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/externals.c?rev=1414442&r1=1414441&r2=1414442&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/externals.c (original)
+++ subversion/trunk/subversion/libsvn_wc/externals.c Tue Nov 27 22:29:23 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/trunk/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1414442&r1=1414441&r2=1414442&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/props.c (original)
+++ subversion/trunk/subversion/libsvn_wc/props.c Tue Nov 27 22:29:23 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/trunk/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc.h?rev=1414442&r1=1414441&r2=1414442&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc.h Tue Nov 27 22:29:23 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 */



Mime
View raw message