subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1404846 [1/4] - in /subversion/branches/ev2-export: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ subversion/libsvn_fs_fs/ subversion/libsvn_ra/ subversion/libsvn_ra_serf/ subversion/...
Date Fri, 02 Nov 2012 00:57:12 GMT
Author: hwright
Date: Fri Nov  2 00:57:09 2012
New Revision: 1404846

URL: http://svn.apache.org/viewvc?rev=1404846&view=rev
Log:
On the ev2-export branch:
Bring up-to-date with trunk.

This causes a few test failures on the branch.

Added:
    subversion/branches/ev2-export/subversion/libsvn_ra/deprecated.h
      - copied unchanged from r1404840, subversion/trunk/subversion/libsvn_ra/deprecated.h
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c
      - copied unchanged from r1404840, subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/   (props changed)
      - copied from r1404840, subversion/trunk/subversion/tests/cmdline/import_tests_data/
    subversion/branches/ev2-export/tools/dev/benchmarks/suite1/generate_charts
      - copied unchanged from r1404840, subversion/trunk/tools/dev/benchmarks/suite1/generate_charts
Removed:
    subversion/branches/ev2-export/subversion/libsvn_wc/tree_conflict_editor.c
Modified:
    subversion/branches/ev2-export/   (props changed)
    subversion/branches/ev2-export/COMMITTERS
    subversion/branches/ev2-export/configure.ac
    subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h
    subversion/branches/ev2-export/subversion/include/svn_delta.h
    subversion/branches/ev2-export/subversion/include/svn_props.h
    subversion/branches/ev2-export/subversion/libsvn_client/add.c
    subversion/branches/ev2-export/subversion/libsvn_client/client.h
    subversion/branches/ev2-export/subversion/libsvn_client/commit.c
    subversion/branches/ev2-export/subversion/libsvn_client/merge.c
    subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c
    subversion/branches/ev2-export/subversion/libsvn_delta/compat.c
    subversion/branches/ev2-export/subversion/libsvn_delta/deprecated.c
    subversion/branches/ev2-export/subversion/libsvn_delta/path_driver.c
    subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/ev2-export/subversion/libsvn_ra/compat.c
    subversion/branches/ev2-export/subversion/libsvn_ra/deprecated.c
    subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
    subversion/branches/ev2-export/subversion/libsvn_ra_serf/util_error.c
    subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c
    subversion/branches/ev2-export/subversion/libsvn_repos/fs-wrap.c
    subversion/branches/ev2-export/subversion/libsvn_repos/replay.c
    subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c
    subversion/branches/ev2-export/subversion/libsvn_subr/io.c
    subversion/branches/ev2-export/subversion/libsvn_subr/named_atomic.c
    subversion/branches/ev2-export/subversion/libsvn_subr/sqlite.c
    subversion/branches/ev2-export/subversion/libsvn_subr/temp_serializer.c
    subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c
    subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h
    subversion/branches/ev2-export/subversion/libsvn_wc/context.c
    subversion/branches/ev2-export/subversion/libsvn_wc/entries.c
    subversion/branches/ev2-export/subversion/libsvn_wc/entries.h
    subversion/branches/ev2-export/subversion/libsvn_wc/lock.c
    subversion/branches/ev2-export/subversion/libsvn_wc/lock.h
    subversion/branches/ev2-export/subversion/libsvn_wc/node.c
    subversion/branches/ev2-export/subversion/libsvn_wc/old-and-busted.c
    subversion/branches/ev2-export/subversion/libsvn_wc/props.c
    subversion/branches/ev2-export/subversion/libsvn_wc/status.c
    subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c
    subversion/branches/ev2-export/subversion/libsvn_wc/util.c
    subversion/branches/ev2-export/subversion/libsvn_wc/wc.h
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_private.h
    subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c
    subversion/branches/ev2-export/subversion/mod_dav_svn/dav_svn.h
    subversion/branches/ev2-export/subversion/mod_dav_svn/liveprops.c
    subversion/branches/ev2-export/subversion/mod_dav_svn/reports/update.c
    subversion/branches/ev2-export/subversion/mod_dav_svn/util.c
    subversion/branches/ev2-export/subversion/mod_dav_svn/version.c
    subversion/branches/ev2-export/subversion/po/es.po
    subversion/branches/ev2-export/subversion/po/pt_BR.po
    subversion/branches/ev2-export/subversion/po/zh_TW.po
    subversion/branches/ev2-export/subversion/tests/cmdline/autoprop_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR1.noo/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR2.doo/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR3.foo/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR4.goo/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR5.moo/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR6/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR6/DIR7/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/import_tests_data/import_tree/DIR6/DIR7/DIR8.noo/   (props changed)
    subversion/branches/ev2-export/subversion/tests/cmdline/merge_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/prop_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py
    subversion/branches/ev2-export/subversion/tests/cmdline/svntest/main.py
    subversion/branches/ev2-export/subversion/tests/cmdline/update_tests.py
    subversion/branches/ev2-export/subversion/tests/libsvn_subr/named_atomic-test.c
    subversion/branches/ev2-export/tools/client-side/svn-bench/null-log-cmd.c
    subversion/branches/ev2-export/tools/dev/benchmarks/suite1/benchmark.py
    subversion/branches/ev2-export/tools/dev/benchmarks/suite1/cronjob
    subversion/branches/ev2-export/tools/dev/benchmarks/suite1/run
    subversion/branches/ev2-export/tools/dist/make-deps-tarball.sh   (props changed)

Propchange: subversion/branches/ev2-export/
------------------------------------------------------------------------------
  Merged /subversion/branches/auto-props-sdc:r1384106-1401643
  Merged /subversion/trunk:r1401904-1404840

Modified: subversion/branches/ev2-export/COMMITTERS
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/COMMITTERS?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/COMMITTERS [UTF-8] (original)
+++ subversion/branches/ev2-export/COMMITTERS [UTF-8] Fri Nov  2 00:57:09 2012
@@ -41,7 +41,7 @@ Blanket commit access:
            lgo   Lieven Govaerts <lgo@mobsol.be>
        hwright   Hyrum Wright <hyrum@hyrumwright.org>
     vgeorgescu   Vlad Georgescu <vgeorgescu@gmail.com>
-       kameshj   Kamesh Jayachandran <kamesh@collab.net>
+       kameshj   Kamesh Jayachandran <kamesh.jayachandran@gmail.com>
       markphip   Mark Phippard <mphippard@collab.net>
       arfrever   Arfrever Frehtes Taifersar Arahesis <arfrever.fta@gmail.com>
           stsp   Stefan Sperling <stsp@elego.de>

Modified: subversion/branches/ev2-export/configure.ac
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/configure.ac?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/configure.ac (original)
+++ subversion/branches/ev2-export/configure.ac Fri Nov  2 00:57:09 2012
@@ -1017,6 +1017,11 @@ AS_HELP_STRING([--enable-maintainer-mode
         CFLAGS="-Wno-system-headers $CFLAGS_KEEP"
         AC_COMPILE_IFELSE([AC_LANG_SOURCE([[]])], [CFLAGS_KEEP="$CFLAGS"])
 
+        dnl Put this flag behind -Wall:
+
+        CFLAGS="$CFLAGS_KEEP -Wno-format-nonliteral"
+        AC_COMPILE_IFELSE([AC_LANG_SOURCE([[]])], [CFLAGS_KEEP="$CFLAGS"])
+
         AC_LANG_POP([C])
         CFLAGS="$CFLAGS_KEEP"
       fi

Modified: subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h (original)
+++ subversion/branches/ev2-export/subversion/include/private/svn_named_atomic.h Fri Nov  2 00:57:09 2012
@@ -83,6 +83,17 @@ svn_atomic_namespace__create(svn_atomic_
                              const char *name,
                              apr_pool_t *result_pool);
 
+/** Removes persistent data structures (files in particular) that got
+ * created for the namespace given by @a name.  Use @a pool for temporary
+ * allocations.
+ *
+ * @note You must not call this while the respective namespace is still
+ * in use. Calling this multiple times for the same namespace is safe.
+ */
+svn_error_t *
+svn_atomic_namespace__cleanup(const char *name,
+                              apr_pool_t *pool);
+
 /** Find the atomic with the specified @a name in namespace @a ns and
  * return it in @a *atomic.  If no object with that name can be found, the
  * behavior depends on @a auto_create.  If it is @c FALSE, @a *atomic will

Modified: subversion/branches/ev2-export/subversion/include/svn_delta.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_delta.h?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_delta.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_delta.h Fri Nov  2 00:57:09 2012
@@ -1324,8 +1324,9 @@ typedef svn_error_t *(*svn_delta_path_dr
  * Each path in @a paths is a const char *. The editor drive will be
  * performed in the same order as @a paths. The paths should be sorted
  * using something like svn_sort_compare_paths to ensure that a depth-first
- * pattern is observed for directory/file baton creation. Some callers may
- * need further customization of the order (ie. libsvn_delta/compat.c).
+ * pattern is observed for directory/file baton creation. If @a sort_paths
+ * is set, the function will sort the paths for you. Some callers may need
+ * further customization of the order (ie. libsvn_delta/compat.c).
  *
  * Use @a scratch_pool for all necessary allocations.
  *
@@ -1335,6 +1336,7 @@ svn_error_t *
 svn_delta_path_driver2(const svn_delta_editor_t *editor,
                        void *edit_baton,
                        const apr_array_header_t *paths,
+                       svn_boolean_t sort_paths,
                        svn_delta_path_driver_cb_func_t callback_func,
                        void *callback_baton,
                        apr_pool_t *scratch_pool);

Modified: subversion/branches/ev2-export/subversion/include/svn_props.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_props.h?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_props.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_props.h Fri Nov  2 00:57:09 2012
@@ -384,6 +384,14 @@ svn_prop_name_is_valid(const char *prop_
  */
 #define SVN_PROP_MERGEINFO SVN_PROP_PREFIX "mergeinfo"
 
+/** Prefix for all Subersion inhertiable properties. */
+#define SVN_PROP_INHERITABLE_PREFIX SVN_PROP_PREFIX "inheritable-"
+
+/** Property used to record inheritable configuration auto-props. */
+#define SVN_PROP_INHERITABLE_AUTO_PROPS SVN_PROP_INHERITABLE_PREFIX "auto-props"
+
+/** Property used to record inheritable configuration ignores. */
+#define SVN_PROP_INHERITABLE_IGNORES SVN_PROP_INHERITABLE_PREFIX "ignores"
 
 /** Meta-data properties.
  *

Modified: subversion/branches/ev2-export/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/add.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/add.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/add.c Fri Nov  2 00:57:09 2012
@@ -56,27 +56,6 @@
 
 /*** Code. ***/
 
-/* This structure is used as baton for enumerating the config entries
-   in the auto-props section.
-*/
-typedef struct auto_props_baton_t
-{
-  /* the file name for which properties are searched */
-  const char *filename;
-
-  /* when this flag is set the hash contains svn:executable */
-  svn_boolean_t have_executable;
-
-  /* when mimetype is not NULL is set the hash contains svn:mime-type */
-  const char *mimetype;
-
-  /* the hash table for storing the property name/value pairs */
-  apr_hash_t *properties;
-
-  /* a pool used for allocating memory */
-  apr_pool_t *pool;
-} auto_props_baton_t;
-
 /* Remove leading and trailing white space from a C string, in place. */
 static void
 trim_string(char **pstr)
@@ -155,114 +134,96 @@ split_props(apr_array_header_t **props,
   *props = temp_props;
 }
 
-/* For one auto-props config entry (NAME, VALUE), if the filename pattern
-   NAME matches BATON->filename case insensitively then add the properties
-   listed in VALUE into BATON->properties.
-   BATON must point to an auto_props_baton_t.
+/* PROPVALS is a hash mapping char * property names to const char * property
+   values.  PROPERTIES can be empty but not NULL.
+
+   If FILENAME doesn't match the filename pattern PATTERN case insensitively,
+   the do nothing.  Otherwise for each 'name':'value' pair in PROPVALS, add
+   a new entry mappying 'name' to a svn_string_t * wrapping the 'value' in
+   PROPERTIES.  The svn_string_t is allocated in the pool used to allocate
+   PROPERTIES, but the char *'s from PROPVALS are re-used in PROPERTIES.
+   If PROPVALS contains a 'svn:mime-type' mapping, then set *MIMETYPE to
+   the mapped value.  Likewise if PROPVALS contains a mapping for
+   svn:executable, then set *HAVE_EXECUTABLE to TRUE.
+
+   Use SCRATCH_POOL for temporary allocations.
 */
-static svn_boolean_t
-auto_props_enumerator(const char *name,
-                      const char *value,
-                      void *baton,
-                      apr_pool_t *pool)
+static void
+get_auto_props_for_pattern(apr_hash_t *properties,
+                           const char **mimetype,
+                           svn_boolean_t *have_executable,
+                           const char *filename,
+                           const char *pattern,
+                           apr_hash_t *propvals,
+                           apr_pool_t *scratch_pool)
 {
-  int i;
-  auto_props_baton_t *autoprops = baton;
-  apr_array_header_t *props;
-
-  /* nothing to do here without a value */
-  if (*value == 0)
-    return TRUE;
+  apr_hash_index_t *hi;
 
   /* check if filename matches and return if it doesn't */
-  if (apr_fnmatch(name, autoprops->filename, APR_FNM_CASE_BLIND) == APR_FNM_NOMATCH)
-    return TRUE;
-
-  split_props(&props, value, autoprops->pool);
-
-  for (i = 0; i < props->nelts; i++)
-    {
-      size_t len;
-      const char *this_value;
-      char *property = APR_ARRAY_IDX(props, i, char *);
-      char *equal_sign = strchr(property, '=');
-
-      if (equal_sign)
-        {
-          *equal_sign = '\0';
-          equal_sign++;
-          trim_string(&equal_sign);
-          unquote_string(&equal_sign);
-          this_value = equal_sign;
-        }
-      else
-        {
-          this_value = "";
-        }
-      trim_string(&property);
-      len = strlen(property);
-
-      if (len > 0)
-        {
-          svn_string_t *propval = apr_palloc(autoprops->pool,
-                                             sizeof(*propval));
-          propval->data = this_value;
-          propval->len = strlen(this_value);
-
-          apr_hash_set(autoprops->properties, property, len, propval);
-          if (strcmp(property, SVN_PROP_MIME_TYPE) == 0)
-            autoprops->mimetype = this_value;
-          else if (strcmp(property, SVN_PROP_EXECUTABLE) == 0)
-            autoprops->have_executable = TRUE;
-        }
+  if (apr_fnmatch(pattern, filename,
+                  APR_FNM_CASE_BLIND) == APR_FNM_NOMATCH)
+    return;
+
+  for (hi = apr_hash_first(scratch_pool, propvals);
+       hi != NULL;
+       hi = apr_hash_next(hi))
+    {
+      const char *propname = svn__apr_hash_index_key(hi);
+      const char *propval = svn__apr_hash_index_val(hi);
+      svn_string_t *propval_str =
+        svn_string_create_empty(apr_hash_pool_get(properties));
+
+      propval_str->data = propval;
+      propval_str->len = strlen(propval);
+
+      apr_hash_set(properties, propname, APR_HASH_KEY_STRING,
+                   propval_str);
+      if (strcmp(propname, SVN_PROP_MIME_TYPE) == 0)
+        *mimetype = propval;
+      else if (strcmp(propname, SVN_PROP_EXECUTABLE) == 0)
+        *have_executable = TRUE;
     }
-  return TRUE;
 }
 
 svn_error_t *
-svn_client__get_auto_props(apr_hash_t **properties,
-                           const char **mimetype,
-                           const char *path,
-                           svn_magic__cookie_t *magic_cookie,
-                           svn_client_ctx_t *ctx,
-                           apr_pool_t *pool)
+svn_client__get_paths_auto_props(apr_hash_t **properties,
+                                 const char **mimetype,
+                                 const char *path,
+                                 svn_magic__cookie_t *magic_cookie,
+                                 apr_hash_t *autoprops,
+                                 svn_client_ctx_t *ctx,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool)
 {
-  svn_config_t *cfg;
-  svn_boolean_t use_autoprops;
-  auto_props_baton_t autoprops;
-
-  /* initialisation */
-  autoprops.properties = apr_hash_make(pool);
-  autoprops.filename = svn_dirent_basename(path, pool);
-  autoprops.pool = pool;
-  autoprops.mimetype = NULL;
-  autoprops.have_executable = FALSE;
-  *properties = autoprops.properties;
+  apr_hash_index_t *hi;
+  svn_boolean_t have_executable = FALSE;
 
-  cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
-                                   APR_HASH_KEY_STRING) : NULL;
+  *properties = apr_hash_make(result_pool);
+  *mimetype = NULL;
 
-  /* check that auto props is enabled */
-  SVN_ERR(svn_config_get_bool(cfg, &use_autoprops,
-                              SVN_CONFIG_SECTION_MISCELLANY,
-                              SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, FALSE));
+  for (hi = apr_hash_first(scratch_pool, autoprops);
+       hi != NULL;
+       hi = apr_hash_next(hi))
+    {
+      const char *pattern = svn__apr_hash_index_key(hi);
+      apr_hash_t *propvals = svn__apr_hash_index_val(hi);
 
-  /* search for auto props */
-  if (use_autoprops)
-    svn_config_enumerate2(cfg, SVN_CONFIG_SECTION_AUTO_PROPS,
-                          auto_props_enumerator, &autoprops, pool);
+      get_auto_props_for_pattern(*properties, mimetype, &have_executable,
+                                 svn_dirent_basename(path, scratch_pool),
+                                 pattern, propvals, scratch_pool);
+    }
 
   /* if mimetype has not been set check the file */
-  if (! autoprops.mimetype)
+  if (! *mimetype)
     {
-      SVN_ERR(svn_io_detect_mimetype2(&autoprops.mimetype, path,
-                                      ctx->mimetypes_map, pool));
+      SVN_ERR(svn_io_detect_mimetype2(mimetype, path, ctx->mimetypes_map,
+                                      result_pool));
 
       /* If we got no mime-type, or if it is "application/octet-stream",
        * try to get the mime-type from libmagic. */
       if (magic_cookie &&
-          (!autoprops.mimetype ||
-           strcmp(autoprops.mimetype, "application/octet-stream") == 0))
+          (!*mimetype ||
+           strcmp(*mimetype, "application/octet-stream") == 0))
         {
           const char *magic_mimetype;
 
@@ -275,29 +236,29 @@ svn_client__get_auto_props(apr_hash_t **
           * returns "text/plain" for them. */
           SVN_ERR(svn_magic__detect_binary_mimetype(&magic_mimetype,
                                                     path, magic_cookie,
-                                                    pool, pool));
+                                                    result_pool,
+                                                    scratch_pool));
           if (magic_mimetype)
-            autoprops.mimetype = magic_mimetype;
+            *mimetype = magic_mimetype;
         }
 
-      if (autoprops.mimetype)
-        apr_hash_set(autoprops.properties, SVN_PROP_MIME_TYPE,
+      if (*mimetype)
+        apr_hash_set(*properties, SVN_PROP_MIME_TYPE,
                      strlen(SVN_PROP_MIME_TYPE),
-                     svn_string_create(autoprops.mimetype, pool));
+                     svn_string_create(*mimetype, result_pool));
     }
 
   /* if executable has not been set check the file */
-  if (! autoprops.have_executable)
+  if (! have_executable)
     {
       svn_boolean_t executable = FALSE;
-      SVN_ERR(svn_io_is_file_executable(&executable, path, pool));
+      SVN_ERR(svn_io_is_file_executable(&executable, path, scratch_pool));
       if (executable)
-        apr_hash_set(autoprops.properties, SVN_PROP_EXECUTABLE,
+        apr_hash_set(*properties, SVN_PROP_EXECUTABLE,
                      strlen(SVN_PROP_EXECUTABLE),
-                     svn_string_create_empty(pool));
+                     svn_string_create_empty(result_pool));
     }
 
-  *mimetype = autoprops.mimetype;
   return SVN_NO_ERROR;
 }
 
@@ -305,6 +266,7 @@ svn_client__get_auto_props(apr_hash_t **
 static svn_error_t *
 add_file(const char *local_abspath,
          svn_magic__cookie_t *magic_cookie,
+         apr_hash_t *autoprops,
          svn_client_ctx_t *ctx,
          apr_pool_t *pool)
 {
@@ -317,21 +279,39 @@ add_file(const char *local_abspath,
   /* Check to see if this is a special file. */
   SVN_ERR(svn_io_check_special_path(local_abspath, &kind, &is_special, pool));
 
-  if (is_special)
-    mimetype = NULL;
-  else
-    /* Get automatic properties */
-    /* This may fail on write-only files:
-       we open them to estimate file type.
-       That's why we postpone the add until after this step. */
-    SVN_ERR(svn_client__get_auto_props(&properties, &mimetype, local_abspath,
-                                       magic_cookie, ctx, pool));
-
   /* Add the file */
   SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, local_abspath,
                                NULL, NULL, pool));
 
   if (is_special)
+    {
+      mimetype = NULL;
+    }
+  else
+    {
+      apr_hash_t *file_autoprops;
+
+      /* Get automatic properties */
+      /* Grab the inherited svn:inheritable-auto-props and config file
+         auto-props for this file if we haven't already got them
+         when iterating over the file's unversioned parents. */
+      if (autoprops == NULL)
+        SVN_ERR(svn_client__get_all_auto_props(
+          &file_autoprops, svn_dirent_dirname(local_abspath,pool),
+          ctx, pool, pool));
+      else
+        file_autoprops = autoprops;
+
+      /* This may fail on write-only files:
+         we open them to estimate file type.
+         That's why we postpone the add until after this step. */
+      SVN_ERR(svn_client__get_paths_auto_props(&properties, &mimetype,
+                                               local_abspath, magic_cookie,
+                                               file_autoprops, ctx, pool,
+                                               pool));
+    }
+
+  if (is_special)
     /* This must be a special file. */
     SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, local_abspath, SVN_PROP_SPECIAL,
                              svn_string_create(SVN_PROP_BOOLEAN_TRUE, pool),
@@ -387,8 +367,8 @@ add_file(const char *local_abspath,
 }
 
 /* Schedule directory DIR_ABSPATH, and some of the tree under it, for
- * addition.  DEPTH is the depth at this
- * point in the descent (it may be changed for recursive calls).
+ * addition.  DEPTH is the depth at this point in the descent (it may
+ * be changed for recursive calls).
  *
  * If DIR_ABSPATH (or any item below DIR_ABSPATH) is already scheduled for
  * addition, add will fail and return an error unless FORCE is TRUE.
@@ -399,8 +379,27 @@ add_file(const char *local_abspath,
  * Use MAGIC_COOKIE (which may be NULL) to detect the mime-type of files
  * if necessary.
  *
+ * If not NULL, *CONFIG_AUTOPROPS is a hash representing the config file and
+ * svn:inheritable-auto-props autoprops which apply to DIR_ABSPATH.  It maps
+ * const char * file patterns to another hash which maps const char *
+ * property names to const char *property values.  If *CONFIG_AUTOPROPS is
+ * NULL and DIR_ABSPATH is unversioned, then this function will populate
+ * *CONFIG_AUTOPROPS (allocated in RESULT_POOL) using DIR_ABSPATH's nearest
+ * versioned parent to determine the svn:inheritable-auto-props which DIR_ABSPATH
+ * will inherit once added.
+ *
+ * If IGNORES is not NULL, then it is an array of const char * ignore patterns
+ * that apply to any children of DIR_ABSPATH.  If REFRESH_IGNORES is TRUE, then
+ * the passed in value of IGNORES (if any) is itself ignored and this function
+ * will gather all ignore patterns applicable to DIR_ABSPATH itself.  Any
+ * recursive calls to this function get the refreshed ignore patterns.  If
+ * IGNORES is NULL and REFRESH_IGNORES is FALSE, then all children of DIR_ABSPATH
+ * are unconditionally added.
+ *
  * If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to allow
- * the user to cancel the operation
+ * the user to cancel the operation.
+ *
+ * Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
 add_dir_recursive(const char *dir_abspath,
@@ -408,14 +407,19 @@ add_dir_recursive(const char *dir_abspat
                   svn_boolean_t force,
                   svn_boolean_t no_ignore,
                   svn_magic__cookie_t *magic_cookie,
+                  apr_hash_t **config_autoprops,
+                  svn_boolean_t refresh_ignores,
+                  apr_array_header_t *ignores,
                   svn_client_ctx_t *ctx,
+                  apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
   apr_pool_t *iterpool;
-  apr_array_header_t *ignores;
   apr_hash_t *dirents;
   apr_hash_index_t *hi;
+  svn_boolean_t entry_exists = FALSE;
+  svn_boolean_t found_unversioned_root = FALSE;
 
   /* Check cancellation; note that this catches recursive calls too. */
   if (ctx->cancel_func)
@@ -423,19 +427,42 @@ add_dir_recursive(const char *dir_abspat
 
   iterpool = svn_pool_create(scratch_pool);
 
+  if (refresh_ignores)
+    SVN_ERR(svn_client__get_all_ignores(&ignores, dir_abspath,
+                                        no_ignore, ctx, scratch_pool,
+                                        scratch_pool));
+
   /* Add this directory to revision control. */
   err = svn_wc_add_from_disk(ctx->wc_ctx, dir_abspath,
                              ctx->notify_func2, ctx->notify_baton2,
                              iterpool);
-  if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
-    svn_error_clear(err);
-  else if (err)
-    return svn_error_trace(err);
+  if (err)
+    {
+      if (err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
+        {
+          svn_error_clear(err);
+          entry_exists = TRUE;
+        }
+      else if (err)
+        {
+          return svn_error_trace(err);
+        }
+    }
 
-  if (!no_ignore)
+  /* For the root of any unversioned subtree, get some or all of the
+     following:
+
+       1) Explicit and inherited svn:inheritable-auto-props properties on
+          DIR_ABSPATH
+       2) Explicit and inherited svn:inheritabled-ignores properties on
+          DIR_ABSPATH
+       3) auto-props from the CTX->CONFIG hash */
+  if (!entry_exists && *config_autoprops == NULL)
     {
-      SVN_ERR(svn_wc_get_ignores2(&ignores, ctx->wc_ctx, dir_abspath,
-                                  ctx->config, scratch_pool, iterpool));
+      SVN_ERR(svn_client__get_all_auto_props(config_autoprops, dir_abspath,
+                                             ctx, result_pool,
+                                             scratch_pool));
+      found_unversioned_root = TRUE;
     }
 
   SVN_ERR(svn_io_get_dirents3(&dirents, dir_abspath, TRUE, scratch_pool,
@@ -460,7 +487,8 @@ add_dir_recursive(const char *dir_abspat
       if (svn_wc_is_adm_dir(name, iterpool))
         continue;
 
-      if ((!no_ignore) && svn_wc_match_ignore_list(name, ignores, iterpool))
+      if (ignores
+          && svn_wc_match_ignore_list(name, ignores, iterpool))
         continue;
 
       /* Construct the full path of the entry. */
@@ -473,14 +501,23 @@ add_dir_recursive(const char *dir_abspat
           if (depth == svn_depth_immediates)
             depth_below_here = svn_depth_empty;
 
+          /* When DIR_ABSPATH is the root of an unversioned subtree then
+             it and all of its children have the same set of ignores.  So
+             save any recursive calls the extra work of finding the same
+             set of ignores. */
+          if (refresh_ignores && !entry_exists)
+            refresh_ignores = FALSE;
+
           SVN_ERR(add_dir_recursive(abspath, depth_below_here,
                                     force, no_ignore, magic_cookie,
-                                    ctx, iterpool));
+                                    config_autoprops, refresh_ignores,
+                                    ignores, ctx, iterpool, iterpool));
         }
       else if ((dirent->kind == svn_node_file || dirent->special)
                && depth >= svn_depth_files)
         {
-          err = add_file(abspath, magic_cookie, ctx, iterpool);
+          err = add_file(abspath, magic_cookie, *config_autoprops, ctx,
+                         iterpool);
           if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
             svn_error_clear(err);
           else
@@ -491,9 +528,440 @@ add_dir_recursive(const char *dir_abspat
   /* Destroy the per-iteration pool. */
   svn_pool_destroy(iterpool);
 
+  /* Reset CONFIG_AUTOPROPS if we just finished processing the root
+     of an unversioned subtree. */
+  if (found_unversioned_root)
+    *config_autoprops = NULL;
+
   return SVN_NO_ERROR;
 }
 
+/* This structure is used as baton for collecting the config entries
+   in the auto-props section and any inherited svn:inheritable-auto-props
+   properties.
+*/
+typedef struct collect_auto_props_baton_t
+{
+  /* the hash table for storing the property name/value pairs */
+  apr_hash_t *autoprops;
+
+  /* a pool used for allocating memory */
+  apr_pool_t *result_pool;
+} collect_auto_props_baton_t;
+
+/* Implements svn_config_enumerator2_t callback.
+
+   For one auto-props config entry (NAME, VALUE), stash a copy of
+   NAME and VALUE, allocated in BATON->POOL, in BATON->AUTOPROP.
+   BATON must point to an collect_auto_props_baton_t.
+*/
+static svn_boolean_t
+all_auto_props_collector(const char *name,
+                         const char *value,
+                         void *baton,
+                         apr_pool_t *pool)
+{
+  collect_auto_props_baton_t *autoprops_baton = baton;
+  apr_array_header_t *autoprops;
+  int i;
+
+  /* nothing to do here without a value */
+  if (*value == 0)
+    return TRUE;
+
+  split_props(&autoprops, value, pool);
+
+  for (i = 0; i < autoprops->nelts; i ++)
+    {
+      size_t len;
+      const char *this_value;
+      char *property = APR_ARRAY_IDX(autoprops, i, char *);
+      char *equal_sign = strchr(property, '=');
+
+      if (equal_sign)
+        {
+          *equal_sign = '\0';
+          equal_sign++;
+          trim_string(&equal_sign);
+          unquote_string(&equal_sign);
+          this_value = equal_sign;
+        }
+      else
+        {
+          this_value = "";
+        }
+      trim_string(&property);
+      len = strlen(property);
+
+      if (len > 0)
+        {
+          apr_hash_t *pattern_hash = apr_hash_get(autoprops_baton->autoprops,
+                                                  name, APR_HASH_KEY_STRING);
+          svn_string_t *propval;
+
+          /* Force reserved boolean property values to '*'. */
+          if (svn_prop_is_boolean(property))
+            {
+              /* SVN_PROP_EXECUTABLE, SVN_PROP_NEEDS_LOCK, SVN_PROP_SPECIAL */
+              propval = svn_string_create("*", autoprops_baton->result_pool);
+            }
+          else
+            {
+              propval = svn_string_create(this_value,
+                                          autoprops_baton->result_pool);
+            }
+
+          if (!pattern_hash)
+            {
+              pattern_hash = apr_hash_make(autoprops_baton->result_pool);
+              apr_hash_set(autoprops_baton->autoprops,
+                           apr_pstrdup(autoprops_baton->result_pool, name),
+                           APR_HASH_KEY_STRING, pattern_hash);
+            }
+          apr_hash_set(pattern_hash,
+                       apr_pstrdup(autoprops_baton->result_pool, property),
+                       APR_HASH_KEY_STRING, propval->data);
+        }
+    }
+  return TRUE;
+}
+
+/* Go up the directory tree from LOCAL_ABSPATH, looking for a versioned
+ * directory.  If found, return its path in *EXISTING_PARENT_ABSPATH.
+ * Otherwise, return SVN_ERR_CLIENT_NO_VERSIONED_PARENT. */
+static svn_error_t *
+find_existing_parent(const char **existing_parent_abspath,
+                     svn_client_ctx_t *ctx,
+                     const char *local_abspath,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  svn_node_kind_t kind;
+  const char *parent_abspath;
+  svn_wc_context_t *wc_ctx = ctx->wc_ctx;
+
+  SVN_ERR(svn_wc_read_kind(&kind, wc_ctx, local_abspath, FALSE, scratch_pool));
+
+  if (kind == svn_node_dir)
+    {
+      svn_boolean_t is_deleted;
+
+      SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted,
+                                             wc_ctx, local_abspath,
+                                             scratch_pool));
+      if (!is_deleted)
+        {
+          *existing_parent_abspath = apr_pstrdup(result_pool, local_abspath);
+          return SVN_NO_ERROR;
+        }
+    }
+
+  if (svn_dirent_is_root(local_abspath, strlen(local_abspath)))
+    return svn_error_create(SVN_ERR_CLIENT_NO_VERSIONED_PARENT, NULL, NULL);
+
+  if (svn_wc_is_adm_dir(svn_dirent_basename(local_abspath, scratch_pool),
+                        scratch_pool))
+    return svn_error_createf(SVN_ERR_RESERVED_FILENAME_SPECIFIED, NULL,
+                             _("'%s' ends in a reserved name"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+
+  parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+
+  if (ctx->cancel_func)
+    SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
+  SVN_ERR(find_existing_parent(existing_parent_abspath, ctx, parent_abspath,
+                               result_pool, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__get_all_auto_props(apr_hash_t **autoprops,
+                               const char *path_or_url,
+                               svn_client_ctx_t *ctx,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
+{
+  int i;
+  apr_array_header_t *inherited_config_auto_props;
+  apr_hash_t *props;
+  svn_opt_revision_t rev;
+  svn_string_t *config_auto_prop;
+  svn_boolean_t use_autoprops;
+  collect_auto_props_baton_t autoprops_baton;
+  svn_error_t *err = NULL;
+  svn_boolean_t target_is_url = svn_path_is_url(path_or_url);
+  svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
+                                                 SVN_CONFIG_CATEGORY_CONFIG,
+                                                 APR_HASH_KEY_STRING) : NULL;
+  *autoprops = apr_hash_make(result_pool);
+  autoprops_baton.result_pool = result_pool;
+  autoprops_baton.autoprops = *autoprops;
+
+  /* Are "traditional" auto-props enabled?  If so grab them from the
+    config.  This is our starting set auto-props, which may be overriden
+    by svn:inheritable-auto-props. */
+  SVN_ERR(svn_config_get_bool(cfg, &use_autoprops,
+                              SVN_CONFIG_SECTION_MISCELLANY,
+                              SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, FALSE));
+  if (use_autoprops)
+    svn_config_enumerate2(cfg, SVN_CONFIG_SECTION_AUTO_PROPS,
+                          all_auto_props_collector, &autoprops_baton,
+                          scratch_pool);
+
+  /* Convert the config file setting (if any) into a hash mapping file
+     patterns to as hash of prop-->val mappings. */
+  if (svn_path_is_url(path_or_url))
+    rev.kind = svn_opt_revision_head;
+  else
+    rev.kind = svn_opt_revision_working;
+
+  /* If PATH_OR_URL is a WC path, then it might be unversioned, in which case
+     we find it's nearest versioned parent. */
+  while (err == NULL)
+    {
+      err = svn_client_propget5(&props, &inherited_config_auto_props,
+                                SVN_PROP_INHERITABLE_AUTO_PROPS, path_or_url,
+                                &rev, &rev, NULL, svn_depth_empty, NULL, ctx,
+                                scratch_pool, scratch_pool);
+      if (err)
+        {
+          if (target_is_url || err->apr_err != SVN_ERR_UNVERSIONED_RESOURCE)
+            return svn_error_trace(err);
+
+          svn_error_clear(err);
+          err = NULL;
+          SVN_ERR(find_existing_parent(&path_or_url, ctx, path_or_url,
+                                       scratch_pool, scratch_pool));
+        }
+      else
+        {
+          break;
+        }
+    }
+
+  /* Stash any explicit PROPS for PARENT_PATH into the inherited props array,
+     since these are actually inherited props for LOCAL_ABSPATH. */
+  config_auto_prop = apr_hash_get(props, path_or_url, APR_HASH_KEY_STRING);
+
+  if (config_auto_prop)
+    {
+      svn_prop_inherited_item_t *new_iprop =
+        apr_palloc(scratch_pool, sizeof(*new_iprop));
+      new_iprop->path_or_url = path_or_url;
+      new_iprop->prop_hash = apr_hash_make(scratch_pool);
+      apr_hash_set(new_iprop->prop_hash,
+                   SVN_PROP_INHERITABLE_AUTO_PROPS,
+                   APR_HASH_KEY_STRING,
+                   config_auto_prop);
+      APR_ARRAY_PUSH(inherited_config_auto_props,
+                     svn_prop_inherited_item_t *) = new_iprop;
+    }
+
+  for (i = 0; i < inherited_config_auto_props->nelts; i++)
+    {
+      apr_hash_index_t *hi;
+      svn_prop_inherited_item_t *elt = APR_ARRAY_IDX(
+        inherited_config_auto_props, i, svn_prop_inherited_item_t *);
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+      for (hi = apr_hash_first(scratch_pool, elt->prop_hash);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          const svn_string_t *propval = svn__apr_hash_index_val(hi);
+          const char *ch = propval->data;
+          svn_stringbuf_t *config_auto_prop_pattern;
+          svn_stringbuf_t *config_auto_prop_val;
+
+          svn_pool_clear(iterpool);
+
+          config_auto_prop_pattern = svn_stringbuf_create_empty(iterpool);
+          config_auto_prop_val = svn_stringbuf_create_empty(iterpool);
+
+          /* Parse svn:inheritable-auto-props value. */
+          while (*ch != '\0')
+            {
+              svn_stringbuf_setempty(config_auto_prop_pattern);
+              svn_stringbuf_setempty(config_auto_prop_val);
+
+              /* Parse the file pattern. */
+              while (*ch != '\0' && *ch != '=' && *ch != '\n')
+                {
+                  svn_stringbuf_appendbyte(config_auto_prop_pattern, *ch);
+                  ch++;
+                }
+
+              svn_stringbuf_strip_whitespace(config_auto_prop_pattern);
+
+              /* Parse the auto-prop group. */
+              while (*ch != '\0' && *ch != '\n')
+                {
+                  svn_stringbuf_appendbyte(config_auto_prop_val, *ch);
+                  ch++;
+                }
+
+              /* Strip leading '=' and whitespace from auto-prop group. */
+              if (config_auto_prop_val->data[0] == '=')
+                svn_stringbuf_remove(config_auto_prop_val, 0, 1);
+              svn_stringbuf_strip_whitespace(config_auto_prop_val);
+
+              all_auto_props_collector(config_auto_prop_pattern->data,
+                                       config_auto_prop_val->data,
+                                       &autoprops_baton,
+                                       scratch_pool);
+
+              /* Skip to next line if any. */
+              while (*ch != '\0' && *ch != '\n')
+                ch++;
+              if (*ch == '\n')
+                ch++;
+            }
+          svn_pool_destroy(iterpool);
+        }
+    }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *svn_client__get_inherited_ignores(apr_array_header_t **ignores,
+                                               const char *path_or_url,
+                                               svn_client_ctx_t *ctx,
+                                               apr_pool_t *result_pool,
+                                               apr_pool_t *scratch_pool)
+{
+  svn_opt_revision_t rev;
+  apr_hash_t *explicit_ignores;
+  apr_array_header_t *inherited_ignores;
+  svn_boolean_t target_is_url = svn_path_is_url(path_or_url);
+  svn_string_t *explicit_prop;
+  int i;
+
+  if (target_is_url)
+    rev.kind = svn_opt_revision_head;
+  else
+    rev.kind = svn_opt_revision_working;
+
+  SVN_ERR(svn_client_propget5(&explicit_ignores, &inherited_ignores,
+                              SVN_PROP_INHERITABLE_IGNORES, path_or_url,
+                              &rev, &rev, NULL, svn_depth_empty, NULL, ctx,
+                              scratch_pool, scratch_pool));
+
+  explicit_prop = apr_hash_get(explicit_ignores, path_or_url,
+                               APR_HASH_KEY_STRING);
+
+  if (explicit_prop)
+    {
+      svn_prop_inherited_item_t *new_iprop =
+        apr_palloc(scratch_pool, sizeof(*new_iprop));
+      new_iprop->path_or_url = path_or_url;
+      new_iprop->prop_hash = apr_hash_make(scratch_pool);
+      apr_hash_set(new_iprop->prop_hash,
+                   SVN_PROP_INHERITABLE_IGNORES,
+                   APR_HASH_KEY_STRING,
+                   explicit_prop);
+      APR_ARRAY_PUSH(inherited_ignores,
+                     svn_prop_inherited_item_t *) = new_iprop;
+    }
+
+  *ignores = apr_array_make(result_pool, 16, sizeof(const char *));
+
+  for (i = 0; i < inherited_ignores->nelts; i++)
+    {
+      svn_prop_inherited_item_t *elt = APR_ARRAY_IDX(
+        inherited_ignores, i, svn_prop_inherited_item_t *);
+      svn_string_t *ignore_val = apr_hash_get(elt->prop_hash,
+                                              SVN_PROP_INHERITABLE_IGNORES,
+                                              APR_HASH_KEY_STRING);
+      if (ignore_val)
+        svn_cstring_split_append(*ignores, ignore_val->data, "\n\r\t\v ",
+                                 FALSE, result_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *svn_client__get_all_ignores(apr_array_header_t **ignores,
+                                         const char *local_abspath,
+                                         svn_boolean_t no_ignore,
+                                         svn_client_ctx_t *ctx,
+                                         apr_pool_t *result_pool,
+                                         apr_pool_t *scratch_pool)
+{
+  apr_hash_t *explicit_ignores;
+  apr_array_header_t *inherited_ignores;
+  svn_error_t *err = NULL;
+  svn_string_t *explicit_prop;
+  int i;
+  svn_opt_revision_t rev;
+
+  rev.kind = svn_opt_revision_working;
+
+  /* LOCAL_ABSPATH might be unversioned, in which case we find its
+     nearest versioned parent. */
+  while (err == NULL)
+    {
+      err = svn_client_propget5(&explicit_ignores, &inherited_ignores,
+                                SVN_PROP_INHERITABLE_IGNORES, local_abspath,
+                                &rev, &rev, NULL, svn_depth_empty, NULL, ctx,
+                                scratch_pool, scratch_pool);
+      if (err)
+        {
+          if (err->apr_err != SVN_ERR_UNVERSIONED_RESOURCE)
+            return svn_error_trace(err);
+
+          svn_error_clear(err);
+          err = NULL;
+          SVN_ERR(find_existing_parent(&local_abspath, ctx, local_abspath,
+                                       scratch_pool, scratch_pool));
+        }
+      else
+        {
+          break;
+        }
+    }
+
+  explicit_prop = apr_hash_get(explicit_ignores, local_abspath,
+                               APR_HASH_KEY_STRING);
+
+  if (explicit_prop)
+    {
+      svn_prop_inherited_item_t *new_iprop =
+        apr_palloc(scratch_pool, sizeof(*new_iprop));
+      new_iprop->path_or_url = local_abspath;
+      new_iprop->prop_hash = apr_hash_make(scratch_pool);
+      apr_hash_set(new_iprop->prop_hash,
+                   SVN_PROP_INHERITABLE_IGNORES,
+                   APR_HASH_KEY_STRING,
+                   explicit_prop);
+      APR_ARRAY_PUSH(inherited_ignores,
+                     svn_prop_inherited_item_t *) = new_iprop;
+    }
+
+  /* Now that we are sure we have an existing parent, get the config ignore
+     and the local ignore patterns... */
+  if (!no_ignore)
+    SVN_ERR(svn_wc_get_ignores2(ignores, ctx->wc_ctx, local_abspath,
+                                ctx->config, result_pool, scratch_pool));
+  else
+    *ignores = apr_array_make(result_pool, 16, sizeof(const char *));
+
+  /* ...and add the inherited ignores to it. */
+  for (i = 0; i < inherited_ignores->nelts; i++)
+    {
+      svn_prop_inherited_item_t *elt = APR_ARRAY_IDX(
+        inherited_ignores, i, svn_prop_inherited_item_t *);
+      svn_string_t *ignore_val = apr_hash_get(elt->prop_hash,
+                                              SVN_PROP_INHERITABLE_IGNORES,
+                                              APR_HASH_KEY_STRING);
+      if (ignore_val)
+        svn_cstring_split_append(*ignores, ignore_val->data, "\n\r\t\v ",
+                                 FALSE, result_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
 
 /* The main logic of the public svn_client_add4.
  *
@@ -512,6 +980,8 @@ add(const char *local_abspath,
   svn_node_kind_t kind;
   svn_error_t *err;
   svn_magic__cookie_t *magic_cookie;
+  apr_hash_t *config_autoprops = NULL;
+  apr_array_header_t *ignores = NULL;
 
   svn_magic__init(&magic_cookie, scratch_pool);
 
@@ -562,10 +1032,12 @@ add(const char *local_abspath,
          and pass depth along no matter what it is, so that the
          target's depth will be set correctly. */
       err = add_dir_recursive(local_abspath, depth, force, no_ignore,
-                              magic_cookie, ctx, scratch_pool);
+                              magic_cookie, &config_autoprops, TRUE, ignores,
+                              ctx, scratch_pool, scratch_pool);
     }
   else if (kind == svn_node_file)
-    err = add_file(local_abspath, magic_cookie, ctx, scratch_pool);
+    err = add_file(local_abspath, magic_cookie, config_autoprops, ctx,
+                   scratch_pool);
   else if (kind == svn_node_none)
     {
       svn_boolean_t tree_conflicted;
@@ -606,58 +1078,6 @@ add(const char *local_abspath,
 }
 
 
-/* Go up the directory tree from LOCAL_ABSPATH, looking for a versioned
- * directory.  If found, return its path in *EXISTING_PARENT_ABSPATH.
- * Otherwise, return SVN_ERR_CLIENT_NO_VERSIONED_PARENT. */
-static svn_error_t *
-find_existing_parent(const char **existing_parent_abspath,
-                     svn_client_ctx_t *ctx,
-                     const char *local_abspath,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool)
-{
-  svn_node_kind_t kind;
-  const char *parent_abspath;
-  svn_wc_context_t *wc_ctx = ctx->wc_ctx;
-
-  SVN_ERR(svn_wc_read_kind(&kind, wc_ctx, local_abspath, FALSE, scratch_pool));
-
-  if (kind == svn_node_dir)
-    {
-      svn_boolean_t is_deleted;
-
-      SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted,
-                                             wc_ctx, local_abspath,
-                                             scratch_pool));
-      if (!is_deleted)
-        {
-          *existing_parent_abspath = apr_pstrdup(result_pool, local_abspath);
-          return SVN_NO_ERROR;
-        }
-    }
-
-  if (svn_dirent_is_root(local_abspath, strlen(local_abspath)))
-    return svn_error_create(SVN_ERR_CLIENT_NO_VERSIONED_PARENT, NULL, NULL);
-
-  if (svn_wc_is_adm_dir(svn_dirent_basename(local_abspath, scratch_pool),
-                        scratch_pool))
-    return svn_error_createf(SVN_ERR_RESERVED_FILENAME_SPECIFIED, NULL,
-                             _("'%s' ends in a reserved name"),
-                             svn_dirent_local_style(local_abspath,
-                                                    scratch_pool));
-
-  parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
-  if (ctx->cancel_func)
-    SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
-  SVN_ERR(find_existing_parent(existing_parent_abspath, ctx, parent_abspath,
-                               result_pool, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
 
 svn_error_t *
 svn_client_add4(const char *path,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/client.h?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/client.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/client.h Fri Nov  2 00:57:09 2012
@@ -326,21 +326,88 @@ svn_client__ra_make_cb_baton(svn_wc_cont
 
 /*** Add/delete ***/
 
-/* Read automatic properties matching PATH from CTX->config.
+/* Read automatic properties matching PATH from AUTOPROPS.  AUTOPROPS
+   is is a hash as per svn_client__get_all_auto_props.
+
    Set *PROPERTIES to a hash containing propname/value pairs
-   (const char * keys mapping to svn_string_t * values), or if
-   auto-props are disabled, set *PROPERTIES to NULL.
+   (const char * keys mapping to svn_string_t * values).  *PROPERTIES
+   may be an empty hash, but will not be NULL.
+
    Set *MIMETYPE to the mimetype, if any, or to NULL.
+
    If MAGIC_COOKIE is not NULL and no mime-type can be determined
    via CTX->config try to detect the mime-type with libmagic.
-   Allocate the hash table, keys, values, and mimetype in POOL. */
-svn_error_t *svn_client__get_auto_props(apr_hash_t **properties,
-                                        const char **mimetype,
-                                        const char *path,
-                                        svn_magic__cookie_t *magic_cookie,
-                                        svn_client_ctx_t *ctx,
-                                        apr_pool_t *pool);
 
+   Allocate the *PROPERTIES and its contents as well as *MIMETYPE, in
+   RESULT_POOL.  Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *svn_client__get_paths_auto_props(
+  apr_hash_t **properties,
+  const char **mimetype,
+  const char *path,
+  svn_magic__cookie_t *magic_cookie,
+  apr_hash_t *autoprops,
+  svn_client_ctx_t *ctx,
+  apr_pool_t *result_pool,
+  apr_pool_t *scratch_pool);
+
+/* Gather all auto-props from CTX->config (or none if auto-props are
+   disabled) and all svn:inheritable-auto-props explicitly set on or inherited
+   by PATH_OR_URL.
+
+   If PATH_OR_URL is an unversioned WC path then gather the
+   svn:inheritable-auto-props inherited by PATH_OR_URL's nearest versioned
+   parent.
+
+   If PATH_OR_URL is a URL ask for the properties @HEAD, if it is a WC
+   path as sfor the working properties.
+
+   Store both types of auto-props in *AUTOPROPS, a hash mapping const
+   char * file patterns to another hash which maps const char * property
+   names to const char *property values.
+
+   If a given property name exists for the same pattern in both the config
+   file and in an a svn:inheritable-auto-props property, the latter overrides the
+   former.  If a given property name exists for the same pattern in two
+   different inherited svn:inheritable-auto-props, then the closer path-wise
+   property overrides the more distant. svn:inheritable-auto-props explicitly set
+   on PATH_OR_URL have the highest precedence and override inherited props
+   and config file settings.
+
+   Allocate *AUTOPROPS in RESULT_POOL.  Use SCRATCH_POOL for temporary
+   allocations. */
+svn_error_t *svn_client__get_all_auto_props(apr_hash_t **autoprops,
+                                            const char *path_or_url,
+                                            svn_client_ctx_t *ctx,
+                                            apr_pool_t *result_pool,
+                                            apr_pool_t *scratch_pool);
+
+/* Get a combined list of ignore patterns from CTX->CONFIG, local ignore
+   patterns on LOCAL_ABSPATH (per the svn:ignore property), and from any
+   svn:inheritable-ignores properties set on, or inherited by, LOCAL_ABSPATH.
+   If LOCAL_ABSPATH is unversioned but is located within a valid working copy,
+   then find its nearest versioned parent path, if any, and return the ignore
+   patterns for that parent.  Return an SVN_ERR_WC_NOT_WORKING_COPY error if
+   LOCAL_ABSPATH is neither a versioned working copy path nor an unversioned
+   path within a working copy.  Store the collected patterns as const char *
+   elements in the array *IGNORES.  Allocate *IGNORES and its contents in
+   RESULT_POOL.  Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *svn_client__get_all_ignores(apr_array_header_t **ignores,
+                                         const char *local_abspath,
+                                         svn_boolean_t no_ignore,
+                                         svn_client_ctx_t *ctx,
+                                         apr_pool_t *result_pool,
+                                         apr_pool_t *scratch_pool);
+
+/* Get a list of ignore patterns defined by the svn:inheritable-ignores
+   properties set on, or inherited by, PATH_OR_URL.  Store the collected
+   patterns as const char * elements in the array *IGNORES.  Allocate
+   *IGNORES and its contents in RESULT_POOL.  Use  SCRATCH_POOL for
+   temporary allocations. */
+svn_error_t *svn_client__get_inherited_ignores(apr_array_header_t **ignores,
+                                               const char *path_or_url,
+                                               svn_client_ctx_t *ctx,
+                                               apr_pool_t *result_pool,
+                                               apr_pool_t *scratch_pool);
 
 /* The main logic for client deletion from a working copy. Deletes PATH
    from CTX->WC_CTX.  If PATH (or any item below a directory PATH) is

Modified: subversion/branches/ev2-export/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/commit.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/commit.c Fri Nov  2 00:57:09 2012
@@ -76,6 +76,13 @@ typedef struct import_ctx_t
 
   /* A magic cookie for mime-type detection. */
   svn_magic__cookie_t *magic_cookie;
+
+  /* Collection of all possible configuration file dictated auto-props and
+     svn:inheritable-auto-props.  A hash mapping const char * file patterns to a
+     second hash which maps const char * property names to const char *
+     property values.  Properties which don't have a value, e.g. svn:executable,
+     simply map the property name to an empty string. */
+  apr_hash_t *autoprops;
 } import_ctx_t;
 
 
@@ -112,9 +119,11 @@ import_file(svn_editor_t *editor,
   if (! dirent->special)
     {
       /* add automatic properties */
-      SVN_ERR(svn_client__get_auto_props(&properties, &mimetype, local_abspath,
-                                         import_ctx->magic_cookie,
-                                         ctx, pool));
+      SVN_ERR(svn_client__get_paths_auto_props(&properties, &mimetype,
+                                               local_abspath,
+                                               import_ctx->magic_cookie,
+                                               import_ctx->autoprops,
+                                               ctx, pool, pool));
     }
 
   if (!properties)
@@ -154,7 +163,8 @@ import_file(svn_editor_t *editor,
 
 /* Return in CHILDREN a mapping of basenames to dirents for the importable
  * children of DIR_ABSPATH.  EXCLUDES is a hash of absolute paths to filter
- * out.  IGNORES, if non-NULL, is a list of basenames to filter out.
+ * out.  IGNORES and MANDATORY_IGNORES, if non-NULL, are lists of basename
+ * patterns to filter out.
  * FILTER_CALLBACK and FILTER_BATON will be called for each absolute path,
  * allowing users to further filter the list of returned entries.
  *
@@ -164,6 +174,7 @@ get_filtered_children(apr_hash_t **child
                       const char *dir_abspath,
                       apr_hash_t *excludes,
                       apr_array_header_t *ignores,
+                      apr_array_header_t *mandatory_ignores,
                       svn_client_import_filter_func_t filter_callback,
                       void *filter_baton,
                       svn_client_ctx_t *ctx,
@@ -224,6 +235,12 @@ get_filtered_children(apr_hash_t **child
           continue;
         }
 
+      if (svn_wc_match_ignore_list(base_name, mandatory_ignores, iterpool))
+        {
+          apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
+          continue;
+        }
+
       if (filter_callback)
         {
           svn_boolean_t filter = FALSE;
@@ -250,6 +267,7 @@ import_dir(svn_editor_t *editor,
            const char *relpath,
            svn_depth_t depth,
            apr_hash_t *excludes,
+           apr_array_header_t *mandatory_ignores,
            svn_boolean_t no_ignore,
            svn_boolean_t ignore_unknown_node_types,
            svn_client_import_filter_func_t filter_callback,
@@ -268,6 +286,7 @@ import_children(const char *dir_abspath,
                 svn_editor_t *editor,
                 svn_depth_t depth,
                 apr_hash_t *excludes,
+                apr_array_header_t *mandatory_ignores,
                 svn_boolean_t no_ignore,
                 svn_boolean_t ignore_unknown_node_types,
                 svn_client_import_filter_func_t filter_callback,
@@ -310,8 +329,8 @@ import_children(const char *dir_abspath,
             depth_below_here = svn_depth_empty;
 
           SVN_ERR(import_dir(editor, local_abspath, relpath,
-                             depth_below_here, excludes, no_ignore,
-                             ignore_unknown_node_types,
+                             depth_below_here, excludes, mandatory_ignores,
+                             no_ignore, ignore_unknown_node_types,
                              filter_callback, filter_baton,
                              import_ctx, ctx, iterpool));
         }
@@ -363,6 +382,9 @@ import_children(const char *dir_abspath,
  * EXCLUDES is a hash whose keys are absolute paths to exclude from
  * the import (values are unused).
  *
+ * MANDATORY_IGNORES is an array of const char * ignore patterns.  Any child
+ * of LOCAL_ABSPATH which matches one or more of the patterns is not imported.
+ *
  * If NO_IGNORE is FALSE, don't import files or directories that match
  * ignore patterns.
  *
@@ -379,6 +401,7 @@ import_dir(svn_editor_t *editor,
            const char *relpath,
            svn_depth_t depth,
            apr_hash_t *excludes,
+           apr_array_header_t *mandatory_ignores,
            svn_boolean_t no_ignore,
            svn_boolean_t ignore_unknown_node_types,
            svn_client_import_filter_func_t filter_callback,
@@ -398,8 +421,8 @@ import_dir(svn_editor_t *editor,
     SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
 
   SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, ignores,
-                                filter_callback, filter_baton, ctx,
-                                pool, pool));
+                                mandatory_ignores, filter_callback,
+                                filter_baton, ctx, pool, pool));
 
   /* Import this directory, but not yet its children. */
   SVN_ERR(svn_hash_keys(&children, dirents, pool));
@@ -427,7 +450,8 @@ import_dir(svn_editor_t *editor,
 
   /* Now import the children recursively. */
   SVN_ERR(import_children(local_abspath, relpath, dirents, editor, depth,
-                          excludes, no_ignore, ignore_unknown_node_types,
+                          excludes, mandatory_ignores, no_ignore,
+                          ignore_unknown_node_types,
                           filter_callback, filter_baton,
                           import_ctx, ctx, pool));
 
@@ -457,6 +481,19 @@ import_dir(svn_editor_t *editor,
  * EXCLUDES is a hash whose keys are absolute paths to exclude from
  * the import (values are unused).
  *
+ * AUTOPROPS is hash of all config file autoprops and
+ * svn:inheritable-auto-props inherited by the import target, see the
+ * IMPORT_CTX member of the same name.
+ *
+ * LOCAL_IGNORES is an array of const char * ignore patterns which
+ * correspond to the svn:ignore property (if any) set on the root of the
+ * repository target and thus dictates which immediate children of that
+ * target should be ignored and not imported.
+ *
+ * MANDATORY_IGNORES is an array of const char * ignore patterns which
+ * correspond to the svn:inheritable-ignores properties (if any) set on
+ * the root of the repository target or inherited by it.
+ *
  * If NO_IGNORE is FALSE, don't import files or directories that match
  * ignore patterns.
  *
@@ -476,6 +513,9 @@ import(const char *local_abspath,
        svn_editor_t *editor,
        svn_depth_t depth,
        apr_hash_t *excludes,
+       apr_hash_t *autoprops,
+       apr_array_header_t *local_ignores,
+       apr_array_header_t *mandatory_ignores,
        svn_boolean_t no_ignore,
        svn_boolean_t ignore_unknown_node_types,
        svn_client_import_filter_func_t filter_callback,
@@ -489,6 +529,7 @@ import(const char *local_abspath,
   const svn_io_dirent2_t *dirent;
   apr_hash_t *props = apr_hash_make(pool);
 
+  import_ctx->autoprops = autoprops;
   svn_magic__init(&import_ctx->magic_cookie, pool);
 
   /* Import a file or a directory tree. */
@@ -507,7 +548,8 @@ import(const char *local_abspath,
       if (dirent->kind == svn_node_dir)
         {
           SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes,
-                                        ignores, filter_callback, filter_baton,
+                                        ignores, mandatory_ignores,
+                                        filter_callback, filter_baton,
                                         ctx, pool, pool));
         }
 
@@ -562,7 +604,12 @@ import(const char *local_abspath,
       svn_boolean_t ignores_match = FALSE;
 
       if (!no_ignore)
-        ignores_match = svn_wc_match_ignore_list(local_abspath, ignores, pool);
+        {
+          SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
+          ignores_match =
+            (svn_wc_match_ignore_list(local_abspath, ignores, pool)
+             || svn_wc_match_ignore_list(local_abspath, local_ignores, pool));
+        }
       if (!ignores_match)
         SVN_ERR(import_file(editor, local_abspath, relpath,
                             dirent, import_ctx, ctx, pool));
@@ -571,12 +618,35 @@ import(const char *local_abspath,
     {
       apr_hash_t *dirents;
 
-      SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, ignores,
+      if (!no_ignore)
+        {
+          int i;
+
+          SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
+
+          /* If we are not creating new repository paths, then we are creating
+             importing new paths to an existing directory.  If that directory
+             has the svn:ignore property set on it, then we want to ignore
+             immediate children that match the pattern(s) defined by that
+             property. */
+          if (!new_entries->nelts)
+            {
+              for (i = 0; i < local_ignores->nelts; i++)
+                {
+                  const char *ignore = APR_ARRAY_IDX(local_ignores, i,
+                                                     const char *);
+                  APR_ARRAY_PUSH(ignores, const char *) = ignore;
+                }          
+            }
+        }
+
+      SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes,
+                                    ignores, mandatory_ignores,
                                     filter_callback, filter_baton, ctx,
                                     pool, pool));
 
       SVN_ERR(import_children(local_abspath, relpath, dirents, editor,
-                              depth, excludes, no_ignore,
+                              depth, excludes, mandatory_ignores, no_ignore,
                               ignore_unknown_node_types,
                               filter_callback, filter_baton,
                               import_ctx, ctx, pool));
@@ -699,6 +769,7 @@ svn_client_import5(const char *path,
                    svn_client_ctx_t *ctx,
                    apr_pool_t *scratch_pool)
 {
+  svn_error_t *err = SVN_NO_ERROR;
   const char *log_msg = "";
   svn_editor_t *editor;
   svn_ra_session_t *ra_session;
@@ -711,6 +782,11 @@ svn_client_import5(const char *path,
   const char *dir;
   apr_hash_t *commit_revprops;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_t *autoprops;
+  apr_array_header_t *mandatory_ignores;
+  svn_opt_revision_t rev;
+  apr_hash_t *local_ignores_hash;
+  apr_array_header_t *local_ignores_arr;
 
   if (svn_path_is_url(path))
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -820,10 +896,39 @@ svn_client_import5(const char *path,
                                  NULL, NULL, NULL, NULL,
                                  scratch_pool, scratch_pool));
 
-  /* Do the import. */
-  SVN_ERR(import(local_abspath, new_entries, editor, depth, excludes,
-                 no_ignore, ignore_unknown_node_types,
-                 filter_callback, filter_baton, ctx, iterpool));
+  /* Get inherited svn:inheritable-auto-props, svn:inheritable-ignores, and
+     svn:ignores for the location we are importing to. */
+  SVN_ERR(svn_client__get_all_auto_props(&autoprops, url, ctx,
+                                         scratch_pool, iterpool));
+  SVN_ERR(svn_client__get_inherited_ignores(&mandatory_ignores, url,
+                                            ctx, scratch_pool, iterpool));
+  rev.kind = svn_opt_revision_head;
+  SVN_ERR(svn_client_propget5(&local_ignores_hash, NULL, SVN_PROP_IGNORE, url,
+                              &rev, &rev, NULL, svn_depth_empty, NULL, ctx,
+                              scratch_pool, scratch_pool));
+  local_ignores_arr = apr_array_make(scratch_pool, 1, sizeof(const char *));
+
+  if (apr_hash_count(local_ignores_hash))
+    {
+      svn_string_t *propval = apr_hash_get(local_ignores_hash, url,
+                                           APR_HASH_KEY_STRING);
+      if (propval)
+        {
+          svn_cstring_split_append(local_ignores_arr, propval->data,
+                                   "\n\r\t\v ", FALSE, scratch_pool);
+        }
+    }
+
+  /* If an error occurred during the commit, abort the edit and return
+     the error.  We don't even care if the abort itself fails.  */
+  if ((err = import(local_abspath, new_entries, editor, depth, excludes,
+                    autoprops, local_ignores_arr, mandatory_ignores,
+                    no_ignore, ignore_unknown_node_types,
+                    filter_callback, filter_baton, ctx, iterpool)))
+    {
+      svn_error_clear(svn_editor_abort(editor));
+      return svn_error_trace(err);
+    }
 
   svn_pool_destroy(iterpool);
 

Modified: subversion/branches/ev2-export/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/merge.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/merge.c Fri Nov  2 00:57:09 2012
@@ -5731,12 +5731,17 @@ get_wc_explicit_mergeinfo_catalog(apr_ha
   svn_opt_revision_t working_revision = { svn_opt_revision_working, { 0 } };
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_hash_index_t *hi;
+  apr_hash_t *externals;
 
   SVN_ERR(svn_client_propget5(subtrees_with_mergeinfo, NULL,
                               SVN_PROP_MERGEINFO, target_abspath,
                               &working_revision, &working_revision, NULL,
                               depth, NULL, ctx, result_pool, scratch_pool));
 
+  SVN_ERR(svn_wc__externals_defined_below(&externals, ctx->wc_ctx,
+                                          target_abspath, scratch_pool,
+                                          scratch_pool));
+
   /* Convert property values to svn_mergeinfo_t. */
   for (hi = apr_hash_first(scratch_pool, *subtrees_with_mergeinfo);
        hi;
@@ -5747,6 +5752,15 @@ get_wc_explicit_mergeinfo_catalog(apr_ha
       svn_mergeinfo_t mergeinfo;
       svn_error_t *err;
 
+      /* svn_client_propget5 picks up file externals with
+         mergeinfo, but we don't want those. */
+      if (apr_hash_get(externals, wc_path, APR_HASH_KEY_STRING))
+        {
+          apr_hash_set(*subtrees_with_mergeinfo, wc_path,
+                       APR_HASH_KEY_STRING, NULL);
+          continue;
+        }
+
       svn_pool_clear(iterpool);
 
       err = svn_mergeinfo_parse(&mergeinfo, mergeinfo_string->data,

Modified: subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c Fri Nov  2 00:57:09 2012
@@ -337,11 +337,9 @@ svn_client_propset_local(const char *pro
 
               ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
             }
-
-          svn_error_clear(err);
         }
-      else
-        SVN_ERR(err);
+
+      SVN_ERR(err);
 
       SVN_WC__CALL_WITH_WRITE_LOCK(
         svn_wc_prop_set4(ctx->wc_ctx, target_abspath, propname,

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/compat.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/compat.c Fri Nov  2 00:57:09 2012
@@ -1725,27 +1725,8 @@ drive_changes(const struct editor_baton 
 
   /* Get a sorted list of Ev1-relative paths.  */
   paths = get_sorted_paths(eb->changes, eb->base_relpath, scratch_pool);
-
-  /* We need to pass SVN_INVALID_REVNUM to the path_driver. It uses this
-     revision whenever it opens directory batons. If we specified a "real"
-     value, such as eb->root.base_revision, then it might use that for a
-     subdirectory *incorrectly*.
-
-     Specifically, log_tests 38 demonstrates that erroneous behavior when
-     it attempts to open "/A" at revision 0 (not there, of course).
-
-     All this said: passing SVN_INVALID_REVNUM to all of those
-     open_directory() calls is not the best behavior either, but it does
-     happen to magically work. (ugh)
-
-     Thankfully, we're moving away from this skitchy behavior to Ev2.
-
-     Final note: every other caller of svn_delta_path_driver() passes
-     SVN_INVALID_REVNUM, so we can't be the only goofball.
-
-     Note: dropping const on the callback_baton.  */
   SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton, paths,
-                                 apply_change, (void *)eb,
+                                 FALSE, apply_change, (void *)eb,
                                  scratch_pool));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/deprecated.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/deprecated.c Fri Nov  2 00:57:09 2012
@@ -39,15 +39,10 @@ svn_delta_path_driver(const svn_delta_ed
                       void *callback_baton,
                       apr_pool_t *scratch_pool)
 {
-  apr_array_header_t *sorted;
-
   /* REVISION is dropped on the floor.  */
 
-  /* Construct a copy of PATHS, then sort them in a depth-first order.  */
-  sorted = apr_array_copy(scratch_pool, paths);
-  qsort(sorted->elts, sorted->nelts, sorted->elt_size, svn_sort_compare_paths);
-
-  return svn_error_trace(svn_delta_path_driver2(editor, edit_baton, sorted,
+  return svn_error_trace(svn_delta_path_driver2(editor, edit_baton, paths,
+                                                TRUE,
                                                 callback_func, callback_baton,
                                                 scratch_pool));
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/path_driver.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/path_driver.c Fri Nov  2 00:57:09 2012
@@ -133,6 +133,7 @@ svn_error_t *
 svn_delta_path_driver2(const svn_delta_editor_t *editor,
                        void *edit_baton,
                        const apr_array_header_t *paths,
+                       svn_boolean_t sort_paths,
                        svn_delta_path_driver_cb_func_t callback_func,
                        void *callback_baton,
                        apr_pool_t *pool)
@@ -151,6 +152,16 @@ svn_delta_path_driver2(const svn_delta_e
 
   subpool = svn_pool_create(pool);
   iterpool = svn_pool_create(pool);
+
+  /* sort paths if necessary */
+  if (sort_paths && paths->nelts > 1)
+    {
+      apr_array_header_t *sorted = apr_array_copy(subpool, paths);
+      qsort(sorted->elts, sorted->nelts, sorted->elt_size,
+            svn_sort_compare_paths);
+      paths = sorted;
+    }
+
   item = apr_pcalloc(subpool, sizeof(*item));
 
   /* If the root of the edit is also a target path, we want to call

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Fri Nov  2 00:57:09 2012
@@ -3160,6 +3160,16 @@ ensure_revprop_namespace(svn_fs_t *fs)
     : SVN_NO_ERROR;
 }
 
+/* Make sure the revprop_namespace member in FS is set. */
+static svn_error_t *
+cleanup_revprop_namespace(svn_fs_t *fs)
+{
+  const char *name = svn_dirent_join(fs->path,
+                                     ATOMIC_REVPROP_NAMESPACE,
+                                     fs->pool);
+  return svn_error_trace(svn_atomic_namespace__cleanup(name, fs->pool));
+}
+
 /* Make sure the revprop_generation member in FS is set and, if necessary,
  * initialized with the latest value stored on disk.
  */
@@ -3213,10 +3223,12 @@ ensure_revprop_timeout(svn_fs_t *fs)
 /* Create an error object with the given MESSAGE and pass it to the
    WARNING member of FS. */
 static void
-log_revprop_cache_init_warning(svn_fs_t *fs, const char *message)
+log_revprop_cache_init_warning(svn_fs_t *fs,
+                               svn_error_t *underlying_err,
+                               const char *message)
 {
   svn_error_t *err = svn_error_createf(SVN_ERR_FS_REPPROP_CACHE_INIT_FAILURE,
-                                       NULL,
+                                       underlying_err,
                                        message, fs->path);
 
   if (fs->warning)
@@ -3244,8 +3256,9 @@ has_revprop_cache(svn_fs_t *fs, apr_pool
        * -> disable the revprop cache for good
        */
       ffd->revprop_cache = NULL;
-      log_revprop_cache_init_warning(fs, "Revprop caching for '%s' disabled"
-                                         " because it would be inefficient.");
+      log_revprop_cache_init_warning(fs, NULL,
+                                     "Revprop caching for '%s' disabled"
+                                     " because it would be inefficient.");
       
       return FALSE;
     }
@@ -3256,12 +3269,11 @@ has_revprop_cache(svn_fs_t *fs, apr_pool
     {
       /* failure -> disable revprop cache for good */
 
-      svn_error_clear(error);
       ffd->revprop_cache = NULL;
-      log_revprop_cache_init_warning(fs, "Revprop caching for '%s' disabled "
-                                         "because SHM "
-                                         "infrastructure for revprop "
-                                         "caching failed to initialize.");
+      log_revprop_cache_init_warning(fs, error,
+                                     "Revprop caching for '%s' disabled "
+                                     "because SHM infrastructure for revprop "
+                                     "caching failed to initialize.");
 
       return FALSE;
     }
@@ -7076,6 +7088,46 @@ choose_delta_base(representation_t **rep
   return SVN_NO_ERROR;
 }
 
+/* Something went wrong and the pool for the rep write is being
+   cleared before we've finished writing the rep.  So we need
+   to remove the rep from the protorevfile and we need to unlock
+   the protorevfile. */
+static apr_status_t
+rep_write_cleanup(void *data)
+{
+  struct rep_write_baton *b = data;
+  const char *txn_id = svn_fs_fs__id_txn_id(b->noderev->id);
+  svn_error_t *err;
+  
+  /* Truncate and close the protorevfile. */
+  err = svn_io_file_trunc(b->file, b->rep_offset, b->pool);
+  if (err)
+    {
+      apr_status_t rc = err->apr_err;
+      svn_error_clear(err);
+      return rc;
+    }
+  err = svn_io_file_close(b->file, b->pool);
+  if (err)
+    {
+      apr_status_t rc = err->apr_err;
+      svn_error_clear(err);
+      return rc;
+    }
+
+  /* Remove our lock */
+  err = unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->pool);
+  if (err)
+    {
+      apr_status_t rc = err->apr_err;
+      svn_error_clear(err);
+      return rc;
+    }
+
+  return APR_SUCCESS;
+}
+
+
 /* Get a rep_write_baton and store it in *WB_P for the representation
    indicated by NODEREV in filesystem FS.  Perform allocations in
    POOL.  Only appropriate for file contents, not for props or
@@ -7139,6 +7191,10 @@ rep_write_get_baton(struct rep_write_bat
   /* Now determine the offset of the actual svndiff data. */
   SVN_ERR(get_file_offset(&b->delta_start, file, b->pool));
 
+  /* Cleanup in case something goes wrong. */
+  apr_pool_cleanup_register(b->pool, b, rep_write_cleanup,
+                            apr_pool_cleanup_null);
+
   /* Prepare to write the svndiff data. */
   svn_txdelta_to_svndiff3(&wh,
                           &whb,
@@ -7310,6 +7366,9 @@ rep_write_contents_close(void *baton)
       b->noderev->data_rep = rep;
     }
 
+  /* Remove cleanup callback. */
+  apr_pool_cleanup_kill(b->pool, b, rep_write_cleanup);
+
   /* Write out the new node-rev information. */
   SVN_ERR(svn_fs_fs__put_node_revision(b->fs, b->noderev->id, b->noderev, FALSE,
                                        b->pool));
@@ -7451,7 +7510,7 @@ get_next_revision_ids(const char **node_
 
   *node_id = apr_pstrdup(pool, str);
 
-  str = svn_cstring_tokenize(" ", &buf);
+  str = svn_cstring_tokenize(" \n", &buf);
   if (! str)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Corrupt 'current' file"));
@@ -8912,7 +8971,10 @@ recover_body(void *baton, apr_pool_t *po
   svn_revnum_t youngest_rev;
   svn_node_kind_t youngest_revprops_kind;
 
-  /* First, we need to know the largest revision in the filesystem. */
+  /* Lose potentially corrupted data in temp files */
+  SVN_ERR(cleanup_revprop_namespace(fs));
+
+  /* We need to know the largest revision in the filesystem. */
   SVN_ERR(recover_get_largest_revision(fs, &max_rev, pool));
 
   /* Get the expected youngest revision */
@@ -9005,7 +9067,7 @@ recover_body(void *baton, apr_pool_t *po
     {
       svn_boolean_t missing = TRUE;
       if (!packed_revprop_available(&missing, fs, max_rev, pool))
-	{
+        {
           if (missing)
             {
               return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
@@ -10153,17 +10215,17 @@ svn_fs_fs__verify(svn_fs_t *fs,
     svn_revnum_t i;
     for (i = start; i <= end; i++)
       {
-      	svn_fs_root_t *root;
+        svn_fs_root_t *root;
 
         svn_pool_clear(iterpool);
 
-      	/* ### TODO: Make sure caches are disabled.
+        /* ### TODO: Make sure caches are disabled.
 
-      	   When this code is called in the library, we want to ensure we
-      	   use the on-disk data --- rather than some data that was read
-      	   in the possibly-distance past and cached since. */
-      	SVN_ERR(svn_fs_fs__revision_root(&root, fs, i, iterpool));
-      	SVN_ERR(svn_fs_fs__verify_root(root, iterpool));
+           When this code is called in the library, we want to ensure we
+           use the on-disk data --- rather than some data that was read
+           in the possibly-distance past and cached since. */
+        SVN_ERR(svn_fs_fs__revision_root(&root, fs, i, iterpool));
+        SVN_ERR(svn_fs_fs__verify_root(root, iterpool));
       }
   }
 
@@ -10924,7 +10986,7 @@ hotcopy_body(void *baton, apr_pool_t *po
                                       iterpool));
 
       /* After completing a full shard, update 'current'. */
-      if (rev % max_files_per_dir == 0)
+      if (max_files_per_dir && rev % max_files_per_dir == 0)
         SVN_ERR(hotcopy_update_current(&dst_youngest, dst_fs, rev, iterpool));
     }
   svn_pool_destroy(iterpool);
@@ -10986,14 +11048,16 @@ hotcopy_body(void *baton, apr_pool_t *po
                                  PATH_TXN_CURRENT, pool));
 
   /* If a revprop generation file exists in the source filesystem,
-   * force a fresh revprop caching namespace for the destination by
-   * setting the generation to zero. We have no idea if the revprops
-   * we copied above really belong to the currently cached generation. */
+   * reset it to zero (since this is on a different path, it will not
+   * overlap with data already in cache).  Also, clean up stale files
+   * used for the named atomics implementation. */
   SVN_ERR(svn_io_check_path(path_revprop_generation(src_fs, pool),
                             &kind, pool));
   if (kind == svn_node_file)
     SVN_ERR(write_revprop_generation_file(dst_fs, 0, pool));
 
+  SVN_ERR(cleanup_revprop_namespace(dst_fs));
+
   /* Hotcopied FS is complete. Stamp it with a format file. */
   SVN_ERR(write_format(svn_dirent_join(dst_fs->path, PATH_FORMAT, pool),
                        dst_ffd->format, max_files_per_dir, TRUE, pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_ra/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/compat.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/compat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/compat.c Fri Nov  2 00:57:09 2012
@@ -903,7 +903,7 @@ svn_ra__get_inherited_props_walk(svn_ra_
       svn_error_t *err;
 
       svn_pool_clear(iterpool);
-      parent_url = svn_uri_dirname(parent_url, iterpool);
+      parent_url = svn_uri_dirname(parent_url, scratch_pool);
       SVN_ERR(svn_ra_reparent(session, parent_url, iterpool));
       err = session->vtable->get_dir(session, NULL, NULL,
                                      &parent_props, "",

Modified: subversion/branches/ev2-export/subversion/libsvn_ra/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/deprecated.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/deprecated.c Fri Nov  2 00:57:09 2012
@@ -33,6 +33,7 @@
 #include "svn_pools.h"
 
 #include "ra_loader.h"
+#include "deprecated.h"
 
 #include "svn_private_config.h"
 
@@ -430,3 +431,27 @@ svn_error_t *svn_ra_get_dir(svn_ra_sessi
   return session->vtable->get_dir(session, dirents, fetched_rev, props,
                                   path, revision, SVN_DIRENT_ALL, pool);
 }
+
+svn_error_t *
+svn_ra_local__deprecated_init(int abi_version,
+                              apr_pool_t *pool,
+                              apr_hash_t *hash)
+{
+  return svn_error_trace(svn_ra_local_init(abi_version, pool, hash));
+}
+
+svn_error_t *
+svn_ra_svn__deprecated_init(int abi_version,
+                            apr_pool_t *pool,
+                            apr_hash_t *hash)
+{
+  return svn_error_trace(svn_ra_svn_init(abi_version, pool, hash));
+}
+
+svn_error_t *
+svn_ra_serf__deprecated_init(int abi_version,
+                             apr_pool_t *pool,
+                             apr_hash_t *hash)
+{
+  return svn_error_trace(svn_ra_serf_init(abi_version, pool, hash));
+}

Modified: subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c?rev=1404846&r1=1404845&r2=1404846&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c Fri Nov  2 00:57:09 2012
@@ -48,6 +48,7 @@
 
 #include "svn_config.h"
 #include "ra_loader.h"
+#include "deprecated.h"
 
 #include "private/svn_ra_private.h"
 #include "svn_private_config.h"
@@ -79,7 +80,7 @@ static const struct ra_lib_defn {
     svn_schemes,
 #ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SVN
     svn_ra_svn__init,
-    svn_ra_svn_init
+    svn_ra_svn__deprecated_init
 #endif
   },
 
@@ -88,7 +89,7 @@ static const struct ra_lib_defn {
     local_schemes,
 #ifdef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL
     svn_ra_local__init,
-    svn_ra_local_init
+    svn_ra_local__deprecated_init
 #endif
   },
 
@@ -97,7 +98,7 @@ static const struct ra_lib_defn {
     dav_schemes,
 #ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SERF
     svn_ra_serf__init,
-    svn_ra_serf_init
+    svn_ra_serf__deprecated_init
 #endif
   },
 



Mime
View raw message