You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2012/09/08 01:05:40 UTC

svn commit: r1382205 - in /subversion/branches/inheritable-props: ./ build/ac-macros/ subversion/include/ subversion/include/private/ subversion/libsvn_diff/ subversion/libsvn_fs_fs/ subversion/libsvn_subr/ subversion/svn/ tools/server-side/svnpubsub/

Author: pburba
Date: Fri Sep  7 23:05:39 2012
New Revision: 1382205

URL: http://svn.apache.org/viewvc?rev=1382205&view=rev
Log:
On the inheritable-props branch: Sync with ^/subversion/trunk through
r1381334.

Modified:
    subversion/branches/inheritable-props/   (props changed)
    subversion/branches/inheritable-props/build/ac-macros/macosx.m4
    subversion/branches/inheritable-props/configure.ac
    subversion/branches/inheritable-props/subversion/include/private/svn_eol_private.h
    subversion/branches/inheritable-props/subversion/include/svn_config.h
    subversion/branches/inheritable-props/subversion/libsvn_diff/diff_file.c
    subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h
    subversion/branches/inheritable-props/subversion/libsvn_subr/cache-membuffer.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/cache_config.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/cmdline.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/config.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/config_file.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/eol.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/io.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/sysinfo.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/temp_serializer.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/utf.c
    subversion/branches/inheritable-props/subversion/libsvn_subr/utf_validate.c
    subversion/branches/inheritable-props/subversion/svn/main.c
    subversion/branches/inheritable-props/tools/server-side/svnpubsub/example.conf
    subversion/branches/inheritable-props/tools/server-side/svnpubsub/svnwcsub.py

Propchange: subversion/branches/inheritable-props/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1381335-1382201

Modified: subversion/branches/inheritable-props/build/ac-macros/macosx.m4
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/build/ac-macros/macosx.m4?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/build/ac-macros/macosx.m4 (original)
+++ subversion/branches/inheritable-props/build/ac-macros/macosx.m4 Fri Sep  7 23:05:39 2012
@@ -19,6 +19,32 @@ dnl ====================================
 dnl
 dnl  Mac OS X specific checks
 
+dnl SVN_LIB_MACHO_ITERATE
+dnl Check for _dyld_image_name and _dyld_image_header availability
+AC_DEFUN(SVN_LIB_MACHO_ITERATE,
+[
+  AC_MSG_CHECKING([for Mach-O dynamic module iteration functions])
+
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+    #include <mach-o/dyld.h>
+    #include <mach-o/loader.h>
+    int check(void) {
+      const struct mach_header *header = _dyld_get_image_header(0);
+      const char *name = _dyld_get_image_name(0);
+      if (name && header) return 1;
+      return 0;
+    }
+  ]],[[]])],[have_macho_iterate=yes],[have_macho_iterate=no])
+
+  if test "$have_macho_iterate" = "yes"; then
+    AC_DEFINE([SVN_HAVE_MACHO_ITERATE], [1],
+              [Is Mach-O low-level _dyld API available?])
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+])
+
 dnl SVN_LIB_MACOS_PLIST
 dnl Assign variables for Mac OS property list support
 AC_DEFUN(SVN_LIB_MACOS_PLIST,

Modified: subversion/branches/inheritable-props/configure.ac
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/configure.ac?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/configure.ac (original)
+++ subversion/branches/inheritable-props/configure.ac Fri Sep  7 23:05:39 2012
@@ -479,8 +479,9 @@ if test "$svn_lib_sasl" = "yes"; then
             [Defined if Cyrus SASL v2 is present on the system])
 fi
 
-dnl Mac OS soecufuc features -------------------
+dnl Mac OS specific features -------------------
 
+SVN_LIB_MACHO_ITERATE
 SVN_LIB_MACOS_PLIST
 SVN_LIB_MACOS_KEYCHAIN
 

Modified: subversion/branches/inheritable-props/subversion/include/private/svn_eol_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/private/svn_eol_private.h?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/private/svn_eol_private.h (original)
+++ subversion/branches/inheritable-props/subversion/include/private/svn_eol_private.h Fri Sep  7 23:05:39 2012
@@ -37,6 +37,20 @@
 extern "C" {
 #endif /* __cplusplus */
 
+/* Constants used by various chunky string processing functions.
+ */
+#if APR_SIZEOF_VOIDP == 8
+#  define SVN__LOWER_7BITS_SET 0x7f7f7f7f7f7f7f7f
+#  define SVN__BIT_7_SET       0x8080808080808080
+#  define SVN__R_MASK          0x0a0a0a0a0a0a0a0a
+#  define SVN__N_MASK          0x0d0d0d0d0d0d0d0d
+#else
+#  define SVN__LOWER_7BITS_SET 0x7f7f7f7f
+#  define SVN__BIT_7_SET       0x80808080
+#  define SVN__R_MASK          0x0a0a0a0a
+#  define SVN__N_MASK          0x0d0d0d0d
+#endif
+
 /* Generic EOL character helper routines */
 
 /* Look for the start of an end-of-line sequence (i.e. CR or LF)

Modified: subversion/branches/inheritable-props/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/svn_config.h?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/svn_config.h (original)
+++ subversion/branches/inheritable-props/subversion/include/svn_config.h Fri Sep  7 23:05:39 2012
@@ -92,6 +92,8 @@ typedef struct svn_config_t svn_config_t
 #define SVN_CONFIG_OPTION_PASSWORD_STORES           "password-stores"
 #define SVN_CONFIG_OPTION_KWALLET_WALLET            "kwallet-wallet"
 #define SVN_CONFIG_OPTION_KWALLET_SVN_APPLICATION_NAME_WITH_PID "kwallet-svn-application-name-with-pid"
+/** @since New in 1.8. */
+#define SVN_CONFIG_OPTION_SSL_CLIENT_CERT_FILE_PROMPT "ssl-client-cert-file-prompt"
 /* The majority of options of the "auth" section
  * has been moved to SVN_CONFIG_CATEGORY_SERVERS. */
 #define SVN_CONFIG_SECTION_HELPERS              "helpers"
@@ -626,6 +628,26 @@ svn_config_get_user_config_path(const ch
                                 const char *fname,
                                 apr_pool_t *pool);
 
+/** Create a deep copy of the config object @a src and return
+ * it in @a cfgp, allocating the memory in @a pool.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_config_dup(svn_config_t **cfgp,
+               svn_config_t *src,
+               apr_pool_t *pool);
+
+/** Create a deep copy of the config hash @a src_hash and return
+ * it in @a cfg_hash, allocating the memory in @a pool.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_config_copy_config(apr_hash_t **cfg_hash,
+                       apr_hash_t *src_hash,
+                       apr_pool_t *pool);
+
 /** @} */
 
 #ifdef __cplusplus

Modified: subversion/branches/inheritable-props/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_diff/diff_file.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_diff/diff_file.c Fri Sep  7 23:05:39 2012
@@ -340,30 +340,17 @@ is_one_at_eof(struct file_info file[], a
 /* Quickly determine whether there is a eol char in CHUNK.
  * (mainly copy-n-paste from eol.c#svn_eol__find_eol_start).
  */
-#if SVN_UNALIGNED_ACCESS_IS_OK
-#if APR_SIZEOF_VOIDP == 8
-#  define LOWER_7BITS_SET 0x7f7f7f7f7f7f7f7f
-#  define BIT_7_SET       0x8080808080808080
-#  define R_MASK          0x0a0a0a0a0a0a0a0a
-#  define N_MASK          0x0d0d0d0d0d0d0d0d
-#else
-#  define LOWER_7BITS_SET 0x7f7f7f7f
-#  define BIT_7_SET       0x80808080
-#  define R_MASK          0x0a0a0a0a
-#  define N_MASK          0x0d0d0d0d
-#endif
-#endif
 
 #if SVN_UNALIGNED_ACCESS_IS_OK
 static svn_boolean_t contains_eol(apr_uintptr_t chunk)
 {
-  apr_uintptr_t r_test = chunk ^ R_MASK;
-  apr_uintptr_t n_test = chunk ^ N_MASK;
+  apr_uintptr_t r_test = chunk ^ SVN__R_MASK;
+  apr_uintptr_t n_test = chunk ^ SVN__N_MASK;
 
-  r_test |= (r_test & LOWER_7BITS_SET) + LOWER_7BITS_SET;
-  n_test |= (n_test & LOWER_7BITS_SET) + LOWER_7BITS_SET;
+  r_test |= (r_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
+  n_test |= (n_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
 
-  return (r_test & n_test & BIT_7_SET) != BIT_7_SET;
+  return (r_test & n_test & SVN__BIT_7_SET) != SVN__BIT_7_SET;
 }
 #endif
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.c Fri Sep  7 23:05:39 2012
@@ -2284,6 +2284,7 @@ get_node_revision_body(node_revision_t *
   SVN_ERR(svn_fs_fs__read_noderev(noderev_p,
                                   svn_stream_from_aprfile2(revision_file, FALSE,
                                                            pool),
+                                  svn_fs_fs__id_txn_id(id) != NULL,
                                   pool));
 
   /* The noderev is not in cache, yet. Add it, if caching has been enabled. */
@@ -2293,6 +2294,7 @@ get_node_revision_body(node_revision_t *
 svn_error_t *
 svn_fs_fs__read_noderev(node_revision_t **noderev_p,
                         svn_stream_t *stream,
+                        svn_boolean_t allow_for_txn_roots,
                         apr_pool_t *pool)
 {
   apr_hash_t *headers;
@@ -2423,7 +2425,9 @@ svn_fs_fs__read_noderev(node_revision_t 
     }
 
   /* Get whether this is a fresh txn root. */
-  value = apr_hash_get(headers, HEADER_FRESHTXNRT, APR_HASH_KEY_STRING);
+  value = allow_for_txn_roots
+        ? apr_hash_get(headers, HEADER_FRESHTXNRT, APR_HASH_KEY_STRING)
+        : NULL;
   noderev->is_fresh_txn_root = (value != NULL);
 
   /* Get the mergeinfo count. */
@@ -4199,6 +4203,8 @@ struct rep_state
 static svn_error_t *
 create_rep_state_body(struct rep_state **rep_state,
                       struct rep_args **rep_args,
+                      apr_file_t **file_hint,
+                      svn_revnum_t *rev_hint,
                       representation_t *rep,
                       svn_fs_t *fs,
                       apr_pool_t *pool)
@@ -4208,7 +4214,43 @@ create_rep_state_body(struct rep_state *
   struct rep_args *ra;
   unsigned char buf[4];
 
-  SVN_ERR(open_and_seek_representation(&rs->file, fs, rep, pool));
+  /* If the hint is
+   * - given,
+   * - refers to a packed revision,
+   * - as does the rep we want to read, and
+   * - refers to the same pack file as the rep
+   * ...
+   */
+  if (   file_hint && rev_hint && *file_hint
+      && *rev_hint < ffd->min_unpacked_rev
+      && rep->revision < ffd->min_unpacked_rev
+      && (   (*rev_hint / ffd->max_files_per_dir)
+          == (rep->revision / ffd->max_files_per_dir)))
+    {
+      /* ... we can re-use the same, already open file object
+       */
+      apr_off_t offset;
+      SVN_ERR(get_packed_offset(&offset, fs, rep->revision, pool));
+
+      offset += rep->offset;
+      SVN_ERR(svn_io_file_seek(*file_hint, APR_SET, &offset, pool));
+
+      rs->file = *file_hint;
+    }
+  else
+    {
+      /* otherwise, create a new file object
+       */
+      SVN_ERR(open_and_seek_representation(&rs->file, fs, rep, pool));
+    }
+
+  /* remember the current file, if suggested by the caller */
+  if (file_hint)
+    *file_hint = rs->file;
+  if (rev_hint)
+    *rev_hint = rep->revision;
+
+  /* continue constructing RS and RA */
   rs->window_cache = ffd->txdelta_window_cache;
   rs->combined_cache = ffd->combined_window_cache;
 
@@ -4240,15 +4282,25 @@ create_rep_state_body(struct rep_state *
 
 /* Read the rep args for REP in filesystem FS and create a rep_state
    for reading the representation.  Return the rep_state in *REP_STATE
-   and the rep args in *REP_ARGS, both allocated in POOL. */
+   and the rep args in *REP_ARGS, both allocated in POOL.
+
+   When reading multiple reps, i.e. a skip delta chain, you may provide
+   non-NULL FILE_HINT and REV_HINT.  The function will use these variables
+   to store the previous call results and tries to re-use them.  This may
+   result in significant savings in I/O for packed files.
+ */
 static svn_error_t *
 create_rep_state(struct rep_state **rep_state,
                  struct rep_args **rep_args,
+                 apr_file_t **file_hint,
+                 svn_revnum_t *rev_hint,
                  representation_t *rep,
                  svn_fs_t *fs,
                  apr_pool_t *pool)
 {
-  svn_error_t *err = create_rep_state_body(rep_state, rep_args, rep, fs, pool);
+  svn_error_t *err = create_rep_state_body(rep_state, rep_args,
+                                           file_hint, rev_hint,
+                                           rep, fs, pool);
   if (err && err->apr_err == SVN_ERR_FS_CORRUPT)
     {
       fs_fs_data_t *ffd = fs->fsap_data;
@@ -4515,13 +4567,16 @@ build_rep_list(apr_array_header_t **list
   struct rep_state *rs;
   struct rep_args *rep_args;
   svn_boolean_t is_cached = FALSE;
+  apr_file_t *last_file = NULL;
+  svn_revnum_t last_revision;
 
   *list = apr_array_make(pool, 1, sizeof(struct rep_state *));
   rep = *first_rep;
 
   while (1)
     {
-      SVN_ERR(create_rep_state(&rs, &rep_args, &rep, fs, pool));
+      SVN_ERR(create_rep_state(&rs, &rep_args, &last_file,
+                               &last_revision, &rep, fs, pool));
       SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool));
       if (is_cached)
         {
@@ -4613,6 +4668,10 @@ read_window(svn_txdelta_window_t **nwin,
 
   SVN_ERR_ASSERT(rs->chunk_index <= this_chunk);
 
+  /* RS->FILE may be shared between RS instances -> make sure we point
+   * to the right data. */
+  SVN_ERR(svn_io_file_seek(rs->file, APR_SET, &rs->off, pool));
+
   /* Skip windows to reach the current chunk if we aren't there yet. */
   while (rs->chunk_index < this_chunk)
     {
@@ -4999,8 +5058,8 @@ svn_fs_fs__get_file_delta_stream(svn_txd
       struct rep_args *rep_args;
 
       /* Read target's base rep if any. */
-      SVN_ERR(create_rep_state(&rep_state, &rep_args, target->data_rep,
-                               fs, pool));
+      SVN_ERR(create_rep_state(&rep_state, &rep_args, NULL, NULL,
+                               target->data_rep, fs, pool));
       /* If that matches source, then use this delta as is. */
       if (rep_args->is_delta
           && (rep_args->is_delta_vs_empty
@@ -5061,10 +5120,27 @@ get_dir_contents(apr_hash_t *entries,
     }
   else if (noderev->data_rep)
     {
+      /* use a temporary pool for temp objects.
+       * Also undeltify content before parsing it. Otherwise, we could only
+       * parse it byte-by-byte.
+       */
+      apr_pool_t *text_pool = svn_pool_create(pool);
+      apr_size_t len = noderev->data_rep->expanded_size
+                     ? noderev->data_rep->expanded_size
+                     : noderev->data_rep->size;
+      svn_stringbuf_t *text = svn_stringbuf_create_ensure(len, text_pool);
+      text->len = len;
+
       /* The representation is immutable.  Read it normally. */
-      SVN_ERR(read_representation(&contents, fs, noderev->data_rep, pool));
-      SVN_ERR(svn_hash_read2(entries, contents, SVN_HASH_TERMINATOR, pool));
+      SVN_ERR(read_representation(&contents, fs, noderev->data_rep, text_pool));
+      SVN_ERR(svn_stream_read(contents, text->data, &text->len));
       SVN_ERR(svn_stream_close(contents));
+
+      /* de-serialize hash */
+      contents = svn_stream_from_stringbuf(text, text_pool);
+      SVN_ERR(svn_hash_read2(entries, contents, SVN_HASH_TERMINATOR, pool));
+
+      svn_pool_destroy(text_pool);
     }
 
   return SVN_NO_ERROR;
@@ -9768,7 +9844,7 @@ verify_walker(representation_t *rep,
   struct rep_args *rep_args;
 
   /* ### Should this be using read_rep_line() directly? */
-  SVN_ERR(create_rep_state(&rs, &rep_args, rep, fs, scratch_pool));
+  SVN_ERR(create_rep_state(&rs, &rep_args, NULL, NULL, rep, fs, scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_fs_fs/fs_fs.h Fri Sep  7 23:05:39 2012
@@ -94,11 +94,13 @@ svn_fs_fs__write_noderev(svn_stream_t *o
                          apr_pool_t *pool);
 
 /* Read a node-revision from STREAM. Set *NODEREV to the new structure,
-   allocated in POOL. */
+   allocated in POOL. If ALLOW_FOR_TXN_ROOTS is FALSE, the is-fresh-txn-root
+   flag will be ignored. */
 /* ### Currently used only by fs_fs.c */
 svn_error_t *
 svn_fs_fs__read_noderev(node_revision_t **noderev,
                         svn_stream_t *stream,
+                        svn_boolean_t allow_for_txn_roots,
                         apr_pool_t *pool);
 
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/cache-membuffer.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/cache-membuffer.c Fri Sep  7 23:05:39 2012
@@ -100,16 +100,12 @@
  * on their hash key.
  */
 
-/* A 4-way associative cache seems to be the best compromise between
+/* A 8-way associative cache seems to be a good compromise between
  * performance (worst-case lookups) and efficiency-loss due to collisions.
  *
  * This value may be changed to any positive integer.
  */
-#define GROUP_SIZE 4
-
-/* We use MD5 for digest size and speed (SHA1 is >2x slower, for instance).
- */
-#define KEY_SIZE APR_MD5_DIGESTSIZE
+#define GROUP_SIZE 8
 
 /* For more efficient copy operations, let'a align all data items properly.
  * Must be a power of 2.
@@ -124,9 +120,9 @@
 /* We don't mark the initialization status for every group but initialize
  * a number of groups at once. That will allow for a very small init flags
  * vector that is likely to fit into the CPU caches even for fairly large
- * caches. For instance, the default of 32 means 8x32 groups per byte, i.e.
- * 8 flags/byte x 32 groups/flag x 4 entries/group x 40 index bytes/entry
- * x 16 cache bytes/index byte = 1kB init vector / 640MB cache.
+ * membuffer caches. For instance, the default of 32 means 8x32 groups per
+ * byte, i.e. 8 flags/byte x 32 groups/flag x 8 entries/group x 40 index
+ * bytes/entry x 8 cache bytes/index byte = 1kB init vector / 640MB cache.
  */
 #define GROUP_INIT_GRANULARITY 32
 
@@ -293,6 +289,12 @@ static svn_error_t* assert_equal_tags(co
 
 #endif /* SVN_DEBUG_CACHE_MEMBUFFER */
 
+/* A 16 byte key type. We use that to identify cache entries.
+ * The notation as just two integer values will cause many compilers
+ * to create better code.
+ */
+typedef apr_uint64_t entry_key_t[2];
+
 /* A single dictionary entry. Since all entries will be allocated once
  * during cache creation, those entries might be either used or unused.
  * An entry is used if and only if it is contained in the doubly-linked
@@ -303,7 +305,7 @@ typedef struct entry_t
 {
   /* Identifying the data item. Only valid for used entries.
    */
-  unsigned char key [KEY_SIZE];
+  entry_key_t key;
 
   /* If NO_OFFSET, the entry is not in used. Otherwise, it is the offset
    * of the cached item's serialized data within the data buffer.
@@ -663,22 +665,11 @@ insert_entry(svn_membuffer_t *cache, ent
  */
 static apr_uint32_t
 get_group_index(svn_membuffer_t **cache,
-                const apr_uint32_t *key)
+                entry_key_t key)
 {
-  apr_uint32_t hash;
-
-  /* Get the group that *must* contain the entry. Fold the hash value
-   * just to be sure (it should not be necessary for perfect hashes).
-   */
-  hash = key[0];
-  hash = key[1] ^ ((hash >> 19) || (hash << 13));
-  hash = key[2] ^ ((hash >> 19) || (hash << 13));
-  hash = key[3] ^ ((hash >> 19) || (hash << 13));
-
   /* select the cache segment to use */
   *cache = &(*cache)[key[0] & ((*cache)->segment_count -1)];
-
-  return hash % (*cache)->group_count;
+  return key[0] % (*cache)->group_count;
 }
 
 /* Reduce the hit count of ENTRY and update the accumunated hit info
@@ -749,7 +740,7 @@ initialize_group(svn_membuffer_t *cache,
 static entry_t *
 find_entry(svn_membuffer_t *cache,
            apr_uint32_t group_index,
-           const unsigned char *to_find,
+           const apr_uint64_t to_find[2],
            svn_boolean_t find_empty)
 {
   entry_t *group;
@@ -770,7 +761,8 @@ find_entry(svn_membuffer_t *cache,
           entry = group;
 
           /* initialize entry for the new key */
-          memcpy(entry->key, to_find, KEY_SIZE);
+          entry->key[0] = to_find[0];
+          entry->key[1] = to_find[1];
         }
 
       return entry;
@@ -779,8 +771,9 @@ find_entry(svn_membuffer_t *cache,
   /* try to find the matching entry
    */
   for (i = 0; i < GROUP_SIZE; ++i)
-    if (group[i].offset != NO_OFFSET &&
-        !memcmp(to_find, group[i].key, KEY_SIZE))
+    if (   group[i].offset != NO_OFFSET
+        && to_find[0] == group[i].key[0]
+        && to_find[1] == group[i].key[1])
       {
         /* found it
          */
@@ -825,7 +818,8 @@ find_entry(svn_membuffer_t *cache,
         }
 
       /* initialize entry for the new key */
-      memcpy(entry->key, to_find, KEY_SIZE);
+      entry->key[0] = to_find[0];
+      entry->key[1] = to_find[1];
     }
 
   return entry;
@@ -1161,7 +1155,7 @@ svn_cache__membuffer_cache_create(svn_me
  */
 static svn_error_t *
 membuffer_cache_set_internal(svn_membuffer_t *cache,
-                             const unsigned char *to_find,
+                             entry_key_t to_find,
                              apr_uint32_t group_index,
                              char *buffer,
                              apr_size_t size,
@@ -1174,13 +1168,8 @@ membuffer_cache_set_internal(svn_membuff
       && cache->max_entry_size >= size
       && ensure_data_insertable(cache, size))
     {
-      /* Remove old data for this key, if that exists.
-       * Get an unused entry for the key and and initialize it with
-       * the serialized item's (future) posion within data buffer.
-       */
-      entry_t *entry = find_entry(cache, group_index, to_find, TRUE);
-      entry->size = size;
-      entry->offset = cache->current_data;
+      /* first, look for a previous entry for the given key */
+      entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
@@ -1191,14 +1180,32 @@ membuffer_cache_set_internal(svn_membuff
 
 #endif
 
+      /* if there is an old version of that entry and the new data fits into
+       * the old spot, just re-use that space. */
+      if (entry && entry->size >= size)
+        {
+          entry->size = size;
+        }
+      else
+        {
+          /* Remove old data for this key, if that exists.
+           * Get an unused entry for the key and and initialize it with
+           * the serialized item's (future) posion within data buffer.
+           */
+          entry = find_entry(cache, group_index, to_find, TRUE);
+          entry->size = size;
+          entry->offset = cache->current_data;
+
+          /* Link the entry properly.
+           */
+          insert_entry(cache, entry);
+        }
+
       /* Copy the serialized item data into the cache.
        */
       if (size)
         memcpy(cache->data + entry->offset, buffer, size);
 
-      /* Link the entry properly.
-       */
-      insert_entry(cache, entry);
       cache->total_writes++;
     }
   else
@@ -1221,7 +1228,7 @@ membuffer_cache_set_internal(svn_membuff
  */
 static svn_error_t *
 membuffer_cache_set(svn_membuffer_t *cache,
-                    const void *key,
+                    entry_key_t key,
                     void *item,
                     svn_cache__serialize_func_t serializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -1265,7 +1272,7 @@ membuffer_cache_set(svn_membuffer_t *cac
 static svn_error_t *
 membuffer_cache_get_internal(svn_membuffer_t *cache,
                              apr_uint32_t group_index,
-                             const unsigned char *to_find,
+                             entry_key_t to_find,
                              char **buffer,
                              apr_size_t *item_size,
                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -1325,7 +1332,7 @@ membuffer_cache_get_internal(svn_membuff
  */
 static svn_error_t *
 membuffer_cache_get(svn_membuffer_t *cache,
-                    const void *key,
+                    entry_key_t key,
                     void **item,
                     svn_cache__deserialize_func_t deserializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -1372,7 +1379,7 @@ membuffer_cache_get(svn_membuffer_t *cac
 static svn_error_t *
 membuffer_cache_get_partial_internal(svn_membuffer_t *cache,
                                      apr_uint32_t group_index,
-                                     const unsigned char *to_find,
+                                     entry_key_t to_find,
                                      void **item,
                                      svn_boolean_t *found,
                                      svn_cache__partial_getter_func_t deserializer,
@@ -1431,7 +1438,7 @@ membuffer_cache_get_partial_internal(svn
  */
 static svn_error_t *
 membuffer_cache_get_partial(svn_membuffer_t *cache,
-                            const void *key,
+                            entry_key_t key,
                             void **item,
                             svn_boolean_t *found,
                             svn_cache__partial_getter_func_t deserializer,
@@ -1463,7 +1470,7 @@ membuffer_cache_get_partial(svn_membuffe
 static svn_error_t *
 membuffer_cache_set_partial_internal(svn_membuffer_t *cache,
                                      apr_uint32_t group_index,
-                                     const unsigned char *to_find,
+                                     entry_key_t to_find,
                                      svn_cache__partial_setter_func_t func,
                                      void *baton,
                                      DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -1563,7 +1570,7 @@ membuffer_cache_set_partial_internal(svn
  */
 static svn_error_t *
 membuffer_cache_set_partial(svn_membuffer_t *cache,
-                            const void *key,
+                            entry_key_t key,
                             svn_cache__partial_setter_func_t func,
                             void *baton,
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -1619,7 +1626,7 @@ typedef struct svn_membuffer_cache_t
    * This makes (very likely) our keys different from all keys used
    * by other svn_membuffer_cache_t instances.
    */
-  apr_uint64_t prefix [APR_MD5_DIGESTSIZE / sizeof(apr_uint64_t)];
+  entry_key_t prefix;
 
   /* A copy of the unmodified prefix. It is being used as a user-visible
    * ID for this cache instance.
@@ -1633,7 +1640,7 @@ typedef struct svn_membuffer_cache_t
 
   /* Temporary buffer containing the hash key for the current access
    */
-  apr_uint64_t combined_key [APR_MD5_DIGESTSIZE / sizeof(apr_uint64_t)];
+  entry_key_t combined_key;
 
   /* a pool for temporary allocations during get() and set()
    */

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/cache_config.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/cache_config.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/cache_config.c Fri Sep  7 23:05:39 2012
@@ -118,7 +118,7 @@ svn_cache__get_global_membuffer_cache(vo
       err = svn_cache__membuffer_cache_create(
           &new_cache,
           (apr_size_t)cache_size,
-          (apr_size_t)(cache_size / 16),
+          (apr_size_t)(cache_size / 10),
           ! svn_cache_config_get()->single_threaded,
           pool);
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/cmdline.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/cmdline.c Fri Sep  7 23:05:39 2012
@@ -526,6 +526,13 @@ svn_cmdline_create_auth_baton(svn_auth_b
 
   if (non_interactive == FALSE)
     {
+      svn_boolean_t ssl_client_cert_file_prompt;
+
+      SVN_ERR(svn_config_get_bool(cfg, &ssl_client_cert_file_prompt,
+                                  SVN_CONFIG_SECTION_AUTH,
+                                  SVN_CONFIG_OPTION_SSL_CLIENT_CERT_FILE_PROMPT,
+                                  FALSE));
+
       /* Two basic prompt providers: username/password, and just username. */
       svn_auth_get_simple_prompt_provider(&provider,
                                           svn_cmdline_auth_simple_prompt,
@@ -539,19 +546,23 @@ svn_cmdline_create_auth_baton(svn_auth_b
          2, /* retry limit */ pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-      /* Three ssl prompt providers, for server-certs, client-certs,
-         and client-cert-passphrases.  */
+      /* SSL prompt providers: server-certs and client-cert-passphrases.  */
       svn_auth_get_ssl_server_trust_prompt_provider
         (&provider, svn_cmdline_auth_ssl_server_trust_prompt, pb, pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
-      svn_auth_get_ssl_client_cert_prompt_provider
-        (&provider, svn_cmdline_auth_ssl_client_cert_prompt, pb, 2, pool);
-      APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
       svn_auth_get_ssl_client_cert_pw_prompt_provider
         (&provider, svn_cmdline_auth_ssl_client_cert_pw_prompt, pb, 2, pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+      /* If configuration allows, add a provider for client-cert path
+         prompting, too. */
+      if (ssl_client_cert_file_prompt)
+        {
+          svn_auth_get_ssl_client_cert_prompt_provider
+            (&provider, svn_cmdline_auth_ssl_client_cert_prompt, pb, 2, pool);
+          APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+        }
     }
   else if (trust_server_cert)
     {

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/config.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/config.c Fri Sep  7 23:05:39 2012
@@ -555,6 +555,43 @@ expand_option_value(svn_config_t *cfg, c
     *opt_x_valuep = NULL;
 }
 
+static void
+svn_config_addsection(svn_config_t *cfg,
+                      const char *section,
+                      cfg_section_t **sec)
+{  
+  cfg_section_t *s;
+
+  s = apr_palloc(cfg->pool, sizeof(cfg_section_t));
+  s->name = apr_pstrdup(cfg->pool, section);
+  if(cfg->section_names_case_sensitive)
+    s->hash_key = s->name;
+  else
+    s->hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
+  s->options = apr_hash_make(cfg->pool);
+  apr_hash_set(cfg->sections, s->hash_key, APR_HASH_KEY_STRING, s);
+  
+  *sec = s;
+}
+
+static void
+svn_config_create_option(cfg_option_t **opt,
+                         const char *option,
+                         const char *value,
+                         apr_pool_t *pool)
+{
+  cfg_option_t *o;
+
+  o = apr_palloc(pool, sizeof(cfg_option_t));
+  o->name = apr_pstrdup(pool, option);
+  o->hash_key = make_hash_key(apr_pstrdup(pool, option));
+
+  o->value = apr_pstrdup(pool, value);
+  o->x_value = NULL;
+  o->expanded = FALSE;
+  
+  *opt = o;
+}
 
 
 void
@@ -612,25 +649,12 @@ svn_config_set(svn_config_t *cfg,
     }
 
   /* Create a new option */
-  opt = apr_palloc(cfg->pool, sizeof(*opt));
-  opt->name = apr_pstrdup(cfg->pool, option);
-  opt->hash_key = make_hash_key(apr_pstrdup(cfg->pool, option));
-
-  opt->value = apr_pstrdup(cfg->pool, value);
-  opt->x_value = NULL;
-  opt->expanded = FALSE;
+  svn_config_create_option(&opt, option, value, cfg->pool);
 
   if (sec == NULL)
     {
       /* Even the section doesn't exist. Create it. */
-      sec = apr_palloc(cfg->pool, sizeof(*sec));
-      sec->name = apr_pstrdup(cfg->pool, section);
-      if(cfg->section_names_case_sensitive)
-        sec->hash_key = sec->name;
-      else
-        sec->hash_key = make_hash_key(apr_pstrdup(cfg->pool, section));
-      sec->options = apr_hash_make(cfg->pool);
-      apr_hash_set(cfg->sections, sec->hash_key, APR_HASH_KEY_STRING, sec);
+      svn_config_addsection(cfg, section, &sec);
     }
 
   apr_hash_set(sec->options, opt->hash_key, APR_HASH_KEY_STRING, opt);
@@ -951,6 +975,94 @@ svn_config_get_server_setting(svn_config
   return retval;
 }
 
+
+svn_error_t *
+svn_config_dup(svn_config_t **cfgp,
+               svn_config_t *src,
+               apr_pool_t *pool)
+{
+  apr_hash_index_t *sectidx;
+  apr_hash_index_t *optidx;
+
+  *cfgp = 0;
+  SVN_ERR(svn_config_create(cfgp, FALSE, pool));
+
+  (*cfgp)->x_values = src->x_values;
+  (*cfgp)->section_names_case_sensitive = src->section_names_case_sensitive;
+
+  for (sectidx = apr_hash_first(pool, src->sections);
+       sectidx != NULL;
+       sectidx = apr_hash_next(sectidx))
+  {
+    const void *sectkey;
+    void *sectval;
+    apr_ssize_t sectkeyLength;
+    cfg_section_t * srcsect;
+    cfg_section_t * destsec;
+
+    apr_hash_this(sectidx, &sectkey, &sectkeyLength, &sectval);
+    srcsect = sectval;
+
+    svn_config_addsection(*cfgp, srcsect->name, &destsec);
+
+    for (optidx = apr_hash_first(pool, srcsect->options);
+         optidx != NULL;
+         optidx = apr_hash_next(optidx))
+    {
+      const void *optkey;
+      void *optval;
+      apr_ssize_t optkeyLength;
+      cfg_option_t *srcopt;
+      cfg_option_t *destopt;
+
+      apr_hash_this(optidx, &optkey, &optkeyLength, &optval);
+      srcopt = optval;
+
+      svn_config_create_option(&destopt, srcopt->name, srcopt->value, pool);
+
+      destopt->value = apr_pstrdup(pool, srcopt->value);
+      destopt->x_value = apr_pstrdup(pool, srcopt->x_value);
+      destopt->expanded = srcopt->expanded;
+      apr_hash_set(destsec->options,
+                   apr_pstrdup(pool, (const char*)optkey),
+                   optkeyLength, destopt);
+    }
+  }
+  
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_config_copy_config(apr_hash_t **cfg_hash,
+                       apr_hash_t *src_hash,
+                       apr_pool_t *pool)
+{
+  apr_hash_index_t *cidx;
+
+  *cfg_hash = apr_hash_make(pool);
+  for (cidx = apr_hash_first(pool, src_hash);
+       cidx != NULL;
+       cidx = apr_hash_next(cidx))
+  {
+    const void *ckey;
+    void *cval;
+    apr_ssize_t ckeyLength;
+    svn_config_t * srcconfig;
+    svn_config_t * destconfig;
+
+    apr_hash_this(cidx, &ckey, &ckeyLength, &cval);
+    srcconfig = cval;
+
+    SVN_ERR(svn_config_dup(&destconfig, srcconfig, pool));
+
+    apr_hash_set(*cfg_hash, 
+                 apr_pstrdup(pool, (const char*)ckey),
+                 ckeyLength, destconfig);
+  }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t*
 svn_config_get_server_setting_int(svn_config_t *cfg,
                                   const char *server_group,

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/config_file.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/config_file.c Fri Sep  7 23:05:39 2012
@@ -1034,6 +1034,13 @@ svn_config_ensure(const char *config_dir
         "# kwallet-svn-application-name-with-pid = yes"                      NL
 #endif
         "###"                                                                NL
+        "### Set ssl-client-cert-file-prompt to 'yes' to cause the client"   NL
+        "### to prompt for a path to a client cert file when the server"     NL
+        "### requests a client cert but no client cert file is found in the" NL
+        "### expected place (see the 'ssl-client-cert-file' option in the"   NL
+        "### 'servers' configuration file). Defaults to 'no'."               NL
+        "# ssl-client-cert-file-prompt = no"                                 NL
+        "###"                                                                NL
         "### The rest of the [auth] section in this file has been deprecated."
                                                                              NL
         "### Both 'store-passwords' and 'store-auth-creds' can now be"       NL

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/eol.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/eol.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/eol.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/eol.c Fri Sep  7 23:05:39 2012
@@ -32,18 +32,6 @@
 
 /* Machine-word-sized masks used in svn_eol__find_eol_start.
  */
-#if APR_SIZEOF_VOIDP == 8
-#  define LOWER_7BITS_SET 0x7f7f7f7f7f7f7f7f
-#  define BIT_7_SET       0x8080808080808080
-#  define R_MASK          0x0a0a0a0a0a0a0a0a
-#  define N_MASK          0x0d0d0d0d0d0d0d0d
-#else
-#  define LOWER_7BITS_SET 0x7f7f7f7f
-#  define BIT_7_SET       0x80808080
-#  define R_MASK          0x0a0a0a0a
-#  define N_MASK          0x0d0d0d0d
-#endif
-
 char *
 svn_eol__find_eol_start(char *buf, apr_size_t len)
 {
@@ -69,19 +57,19 @@ svn_eol__find_eol_start(char *buf, apr_s
     /* This is a variant of the well-known strlen test: */
     apr_uintptr_t chunk = *(const apr_uintptr_t *)buf;
 
-    /* A byte in R_TEST is \0, iff it was \r in *BUF.
-     * Similarly, N_TEST is an indicator for \n. */
-    apr_uintptr_t r_test = chunk ^ R_MASK;
-    apr_uintptr_t n_test = chunk ^ N_MASK;
-
-    /* A byte in R_TEST can by < 0x80, iff it has been \0 before
-     * (i.e. \r in *BUF). Dito for N_TEST. */
-    r_test |= (r_test & LOWER_7BITS_SET) + LOWER_7BITS_SET;
-    n_test |= (n_test & LOWER_7BITS_SET) + LOWER_7BITS_SET;
+    /* A byte in SVN__R_TEST is \0, iff it was \r in *BUF.
+     * Similarly, SVN__N_TEST is an indicator for \n. */
+    apr_uintptr_t r_test = chunk ^ SVN__R_MASK;
+    apr_uintptr_t n_test = chunk ^ SVN__N_MASK;
+
+    /* A byte in SVN__R_TEST can by < 0x80, iff it has been \0 before
+     * (i.e. \r in *BUF). Dito for SVN__N_TEST. */
+    r_test |= (r_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
+    n_test |= (n_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
 
     /* Check whether at least one of the words contains a byte <0x80
      * (if one is detected, there was a \r or \n in CHUNK). */
-    if ((r_test & n_test & BIT_7_SET) != BIT_7_SET)
+    if ((r_test & n_test & SVN__BIT_7_SET) != SVN__BIT_7_SET)
       break;
   }
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/io.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/io.c Fri Sep  7 23:05:39 2012
@@ -3427,30 +3427,60 @@ svn_error_t *
 svn_io_read_length_line(apr_file_t *file, char *buf, apr_size_t *limit,
                         apr_pool_t *pool)
 {
+  /* variables */
+  apr_size_t total_read = 0;
+  svn_boolean_t eof = FALSE;
   const char *name;
   svn_error_t *err;
-  apr_size_t i;
-  char c;
+  apr_size_t buf_size = *limit;
 
-  for (i = 0; i < *limit; i++)
+  while (buf_size > 0)
     {
-      SVN_ERR(svn_io_file_getc(&c, file, pool));
-      /* Note: this error could be APR_EOF, which
-         is totally fine.  The caller should be aware of
-         this. */
-
-      if (c == '\n')
+      /* read a fair chunk of data at once. But don't get too ambitious
+       * as that would result in too much waste. Also make sure we can
+       * put a NUL after the last byte read.
+       */
+      apr_size_t to_read = buf_size < 129 ? buf_size - 1 : 128;
+      apr_size_t bytes_read = 0;
+      char *eol;
+
+      /* read data block (or just a part of it) */
+      SVN_ERR(svn_io_file_read_full2(file, buf, to_read,
+                                     &bytes_read, &eof, pool));
+
+      /* look or a newline char */
+      buf[bytes_read] = 0;
+      eol = strchr(buf, '\n');
+      if (eol)
         {
-          buf[i] = '\0';
-          *limit = i;
+          apr_off_t offset = (eol + 1 - buf) - (apr_off_t)bytes_read;
+          
+          *eol = 0;
+          *limit = total_read + (eol - buf);
+
+          /* correct the file pointer:
+           * appear as though we just had read the newline char
+           */
+          SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool));
+
           return SVN_NO_ERROR;
         }
-      else
+      else if (eof)
         {
-          buf[i] = c;
+          /* no EOL found but we hit the end of the file.
+           * Generate a nice EOF error object and return it.
+           */
+          char dummy;
+          SVN_ERR(svn_io_file_getc(&dummy, file, pool));
         }
+
+      /* next data chunk */
+      buf_size -= bytes_read;
+      buf += bytes_read;
+      total_read += bytes_read;
     }
 
+  /* buffer limit has been exceeded without finding the EOL */
   err = svn_io_file_name_get(&name, file, pool);
   if (err)
     name = NULL;

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/sysinfo.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/sysinfo.c Fri Sep  7 23:05:39 2012
@@ -61,6 +61,11 @@
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
+#ifdef SVN_HAVE_MACHO_ITERATE
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#endif
+
 #if HAVE_UNAME
 static const char *canonical_host_from_uname(apr_pool_t *pool);
 # ifndef SVN_HAVE_MACOS_PLIST
@@ -76,7 +81,12 @@ static const apr_array_header_t *win32_s
 
 #ifdef SVN_HAVE_MACOS_PLIST
 static const char *macos_release_name(apr_pool_t *pool);
-#endif  /* SVN_HAVE_MACOS_PLIST */
+#endif
+
+#ifdef SVN_HAVE_MACHO_ITERATE
+static const apr_array_header_t *macos_shared_libs(apr_pool_t *pool);
+#endif
+
 
 #if LINUX
 static const char *linux_release_name(apr_pool_t *pool);
@@ -144,6 +154,8 @@ svn_sysinfo__loaded_libs(apr_pool_t *poo
 {
 #ifdef WIN32
   return win32_shared_libs(pool);
+#elif defined(SVN_HAVE_MACHO_ITERATE)
+  return macos_shared_libs(pool);
 #else
   return NULL;
 #endif
@@ -841,6 +853,7 @@ win32_shared_libs(apr_pool_t *pool)
 }
 #endif /* WIN32 */
 
+
 #ifdef SVN_HAVE_MACOS_PLIST
 /* Load the SystemVersion.plist or ServerVersion.plist file into a
    property list. Set SERVER to TRUE if the file read was
@@ -1024,3 +1037,93 @@ macos_release_name(apr_pool_t *pool)
   return NULL;
 }
 #endif  /* SVN_HAVE_MACOS_PLIST */
+
+#ifdef SVN_HAVE_MACHO_ITERATE
+/* List the shared libraries loaded by the current process.
+   Ignore frameworks and system libraries, they're just clutter. */
+static const apr_array_header_t *
+macos_shared_libs(apr_pool_t *pool)
+{
+  static const char slb_prefix[] = "/usr/lib/system/";
+  static const char fwk_prefix[] = "/System/Library/Frameworks/";
+  static const char pfk_prefix[] = "/System/Library/PrivateFrameworks/";
+
+  const int slb_prefix_len = strlen(slb_prefix);
+  const int fwk_prefix_len = strlen(fwk_prefix);
+  const int pfk_prefix_len = strlen(pfk_prefix);
+
+  apr_array_header_t *result = NULL;
+  apr_array_header_t *dylibs = NULL;
+
+  uint32_t i;
+  for (i = 0;; ++i)
+    {
+      const struct mach_header *header = _dyld_get_image_header(i);
+      const char *filename = _dyld_get_image_name(i);
+      const char *version;
+      char *truename;
+      svn_sysinfo__loaded_lib_t *lib;
+
+      if (!(header && filename))
+        break;
+
+      switch (header->cputype)
+        {
+        case CPU_TYPE_I386:      version = _("Intel"); break;
+        case CPU_TYPE_X86_64:    version = _("Intel 64-bit"); break;
+        case CPU_TYPE_POWERPC:   version = _("PowerPC"); break;
+        case CPU_TYPE_POWERPC64: version = _("PowerPC 64-bit"); break;
+        default:
+          version = NULL;
+        }
+
+      if (0 == apr_filepath_merge(&truename, "", filename,
+                                  APR_FILEPATH_NATIVE
+                                  | APR_FILEPATH_TRUENAME,
+                                  pool))
+        filename = truename;
+      else
+        filename = apr_pstrdup(pool, filename);
+
+      if (0 == strncmp(filename, slb_prefix, slb_prefix_len)
+          || 0 == strncmp(filename, fwk_prefix, fwk_prefix_len)
+          || 0 == strncmp(filename, pfk_prefix, pfk_prefix_len))
+        {
+          /* Ignore frameworks and system libraries. */
+          continue;
+        }
+
+      if (header->filetype == MH_EXECUTE)
+        {
+          /* Make sure the program filename is first in the list */
+          if (!result)
+            {
+              result = apr_array_make(pool, 32, sizeof(*lib));
+            }
+          lib = &APR_ARRAY_PUSH(result, svn_sysinfo__loaded_lib_t);
+        }
+      else
+        {
+          if (!dylibs)
+            {
+              dylibs = apr_array_make(pool, 32, sizeof(*lib));
+            }
+          lib = &APR_ARRAY_PUSH(dylibs, svn_sysinfo__loaded_lib_t);
+        }
+
+      lib->name = filename;
+      lib->version = version;
+    }
+
+  /* Gather results into one array. */
+  if (dylibs)
+    {
+      if (result)
+        apr_array_cat(result, dylibs);
+      else
+        result = dylibs;
+    }
+
+  return result;
+}
+#endif  /* SVN_HAVE_MACHO_ITERATE */

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/temp_serializer.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/temp_serializer.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/temp_serializer.c Fri Sep  7 23:05:39 2012
@@ -51,7 +51,9 @@ typedef struct source_stack_t
   /* offset within the target buffer to where the structure got copied */
   apr_size_t target_offset;
 
-  /* parent stack entry. Will be NULL for the root entry. */
+  /* parent stack entry. Will be NULL for the root entry.
+   * Items in the svn_temp_serializer__context_t recycler will use this
+   * to link to the next unused item. */
   struct source_stack_t *upper;
 } source_stack_t;
 
@@ -70,6 +72,9 @@ struct svn_temp_serializer__context_t
    * process has been finished. However, it is not necessarily NULL when
    * the application end serialization. */
   source_stack_t *source;
+
+  /* unused stack elements will be put here for later reuse. */
+  source_stack_t *recycler;
 };
 
 /* Make sure the serialized data len is a multiple of the default alignment,
@@ -110,6 +115,7 @@ svn_temp_serializer__init(const void *so
   svn_temp_serializer__context_t *context = apr_palloc(pool, sizeof(*context));
   context->pool = pool;
   context->buffer = svn_stringbuf_create_ensure(init_size, pool);
+  context->recycler = NULL;
 
   /* If a source struct has been given, make it the root struct. */
   if (source_struct)
@@ -168,6 +174,9 @@ svn_temp_serializer__init_append(void *b
   context->source->target_offset = (char *)source_struct - (char *)buffer;
   context->source->upper = NULL;
 
+  /* initialize the RECYCLER */
+  context->recycler = NULL;
+
   /* done */
   return context;
 }
@@ -219,9 +228,16 @@ svn_temp_serializer__push(svn_temp_seria
                           apr_size_t struct_size)
 {
   const void *source = *source_struct;
+  source_stack_t *new;
 
-  /* create a new entry for the structure stack */
-  source_stack_t *new = apr_palloc(context->pool, sizeof(*new));
+  /* recycle an old entry or create a new one for the structure stack */
+  if (context->recycler)
+    {
+      new = context->recycler;
+      context->recycler = new->upper;
+    }
+  else
+    new = apr_palloc(context->pool, sizeof(*new));
 
   /* the serialized structure must be properly aligned */
   if (source)
@@ -250,11 +266,17 @@ svn_temp_serializer__push(svn_temp_seria
 void
 svn_temp_serializer__pop(svn_temp_serializer__context_t *context)
 {
+  source_stack_t *old = context->source;
+  
   /* we may pop the original struct but not further */
   assert(context->source);
 
   /* one level up the structure stack */
   context->source = context->source->upper;
+
+  /* put the old stack element into the recycler for later reuse */
+  old->upper = context->recycler;
+  context->recycler = old;
 }
 
 /* Serialize a string referenced from the current structure within the

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/utf.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/utf.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/utf.c Fri Sep  7 23:05:39 2012
@@ -939,7 +939,7 @@ svn_utf_cstring_from_utf8(const char **d
   xlate_handle_node_t *node;
   svn_error_t *err;
 
-  SVN_ERR(check_utf8(src, strlen(src), pool));
+  SVN_ERR(check_cstring_utf8(src, pool));
 
   SVN_ERR(get_uton_xlate_handle_node(&node, pool));
   err = convert_cstring(dest, src, node, pool);
@@ -960,7 +960,7 @@ svn_utf_cstring_from_utf8_ex2(const char
   const char *convset_key = get_xlate_key(topage, SVN_APR_UTF8_CHARSET,
                                           pool);
 
-  SVN_ERR(check_utf8(src, strlen(src), pool));
+  SVN_ERR(check_cstring_utf8(src, pool));
 
   SVN_ERR(get_xlate_handle_node(&node, topage, SVN_APR_UTF8_CHARSET,
                                 convset_key, pool));

Modified: subversion/branches/inheritable-props/subversion/libsvn_subr/utf_validate.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_subr/utf_validate.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_subr/utf_validate.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_subr/utf_validate.c Fri Sep  7 23:05:39 2012
@@ -57,6 +57,7 @@
  */
 
 #include "private/svn_utf_private.h"
+#include "private/svn_eol_private.h"
 
 /* Lookup table to categorise each octet in the string. */
 static const char octet_category[256] = {
@@ -249,12 +250,90 @@ static const char machine [9][14] = {
    FSM_ERROR},        /* 0xf5-0xff */
 };
 
+/* Scan MAX_LEN bytes in *DATA for non-ASCII chars. Return the position
+ * of the first non-ASCII char or DATA + MAX_LEN if all were ASCII.
+ */
+static const char *
+first_non_ascii_char(const char *data, apr_size_t max_len)
+{
+#if !SVN_UNALIGNED_ACCESS_IS_OK
+
+  /* On some systems, we need to make sure that buf is properly aligned
+   * for chunky data access.
+   */
+  if ((apr_uintptr_t)data & (sizeof(apr_uintptr_t)-1))
+    {
+      apr_size_t len = (~(apr_uintptr_t)data) & (sizeof(apr_uintptr_t)-1);
+      if (len > max_len)
+        len = max_len;
+      max_len -= len;
+
+      for (; len > 0; ++data, --len)
+          if (*data < 0)
+            return data;
+    }
+    
+#endif
+    
+  /* Scan the input one machine word at a time. */
+  for (; max_len > sizeof(apr_uintptr_t)
+       ; data += sizeof(apr_uintptr_t), max_len -= sizeof(apr_uintptr_t))
+    if (*(const apr_uintptr_t *)data & SVN__BIT_7_SET)
+      break;
+
+  /* The remaining odd bytes will be examined the naive way: */
+  for (; max_len > 0; ++data, --max_len)
+    if (*data < 0)
+      return data;
+
+  return data;
+}
+
+/* Scan the C string in *DATA for non-ASCII chars. Return the position
+ * of either the first non-ASCII char or the terminating NUL.
+ */
+static const char *
+first_non_ascii_char_cstring(const char *data)
+{
+  /* We need to make sure that BUF is properly aligned for chunky data
+   * access because we don't know the string's length. Unaligned chunk
+   * read access beyond the NUL terminator could therefore result in a
+   * segfault.
+   */
+  for (; (apr_uintptr_t)data & (sizeof(apr_uintptr_t)-1); ++data)
+    if (*data <= 0)
+      return data;
+
+  /* Scan the input one machine word at a time. */
+  for (; ; data += sizeof(apr_uintptr_t))
+    {
+      /* Check for non-ASCII chars: */
+      apr_uintptr_t chunk = *(const apr_uintptr_t *)data;
+      if (chunk & SVN__BIT_7_SET)
+        break;
+
+      /* This is the well-known strlen test: */
+      chunk |= (chunk & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
+      if ((chunk & SVN__BIT_7_SET) != SVN__BIT_7_SET)
+        break;
+    }
+
+  /* The remaining odd bytes will be examined the naive way: */
+  for (; ; ++data)
+    if (*data <= 0)
+      return data;
+
+  return data;
+}
 
 const char *
 svn_utf__last_valid(const char *data, apr_size_t len)
 {
-  const char *start = data, *end = data + len;
+  const char *start = first_non_ascii_char(data, len);
+  const char *end = data + len;
   int state = FSM_START;
+
+  data = start;
   while (data < end)
     {
       unsigned char octet = *data++;
@@ -270,6 +349,8 @@ svn_boolean_t
 svn_utf__cstring_is_valid(const char *data)
 {
   int state = FSM_START;
+  data = first_non_ascii_char_cstring(data);
+
   while (*data)
     {
       unsigned char octet = *data++;
@@ -284,6 +365,8 @@ svn_utf__is_valid(const char *data, apr_
 {
   const char *end = data + len;
   int state = FSM_START;
+  data = first_non_ascii_char(data, len);
+
   while (data < end)
     {
       unsigned char octet = *data++;
@@ -296,8 +379,11 @@ svn_utf__is_valid(const char *data, apr_
 const char *
 svn_utf__last_valid2(const char *data, apr_size_t len)
 {
-  const char *start = data, *end = data + len;
+  const char *start = first_non_ascii_char(data, len);
+  const char *end = data + len;
   int state = FSM_START;
+
+  data = start;
   while (data < end)
     {
       unsigned char octet = *data++;

Modified: subversion/branches/inheritable-props/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/svn/main.c?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/svn/main.c (original)
+++ subversion/branches/inheritable-props/subversion/svn/main.c Fri Sep  7 23:05:39 2012
@@ -777,9 +777,9 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "     merging the other way, into a trunk working copy.\n"
 "\n"
 "         trunk  --+----------o------o-o-------------o--\n"
-"                   \\           \\          \\     /\n"
-"                    \\         merge       merge merge\n"
-"                     \\           \\          \\ /\n"
+"                   \\            \\           \\      /\n"
+"                    \\          merge      merge  merge\n"
+"                     \\            \\           \\  /\n"
 "         feature      +--o-o-------o----o-o----o-------\n"
 "\n"
 "     In this pattern, a merge from the parent branch to the feature branch\n"
@@ -795,9 +795,9 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "                                 ............\n"
 "                                .            .\n"
 "         trunk  --+------------L--------------R------\n"
-"                   \\                          \\\n"
-"                    \\                         |\n"
-"                     \\                        v\n"
+"                   \\                           \\\n"
+"                    \\                          |\n"
+"                     \\                         v\n"
 "         feature      +------------------------o-----\n"
 "                             r100            r200\n"
 "\n"
@@ -829,9 +829,9 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "\n"
 "                    rW                   rX\n"
 "         trunk ------+--------------------L------------------o\n"
-"                      \\                   .                 ^\n"
-"                       \\                   .............   /\n"
-"                        \\                               . /\n"
+"                      \\                    .                 ^\n"
+"                       \\                    .............   /\n"
+"                        \\                                . /\n"
 "         feature         +--------------------------------R\n"
 "\n"
 "     In the diagram above, L marks the left side (trunk@X) and R marks the\n"

Modified: subversion/branches/inheritable-props/tools/server-side/svnpubsub/example.conf
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/tools/server-side/svnpubsub/example.conf?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/tools/server-side/svnpubsub/example.conf (original)
+++ subversion/branches/inheritable-props/tools/server-side/svnpubsub/example.conf Fri Sep  7 23:05:39 2012
@@ -3,6 +3,7 @@
 [DEFAULT]
 svnbin: /usr/local/bin/svn
 streams: http://svn.example.org:2069/commits/xml
+hook: /usr/bin/true
 
 ## The values below are used by ConfigParser's interpolation syntax.
 ## See http://docs.python.org/library/configparser

Modified: subversion/branches/inheritable-props/tools/server-side/svnpubsub/svnwcsub.py
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/tools/server-side/svnpubsub/svnwcsub.py?rev=1382205&r1=1382204&r2=1382205&view=diff
==============================================================================
--- subversion/branches/inheritable-props/tools/server-side/svnpubsub/svnwcsub.py (original)
+++ subversion/branches/inheritable-props/tools/server-side/svnpubsub/svnwcsub.py Fri Sep  7 23:05:39 2012
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# encoding: UTF-8
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -72,6 +73,22 @@ def svn_info(svnbin, env, path):
         info[line[:idx]] = line[idx+1:].strip()
     return info
 
+try:
+    import glob
+    glob.iglob
+    def is_emptydir(path):
+        # ### If the directory contains only dotfile children, this will readdir()
+        # ### the entire directory.  But os.readdir() is not exposed to us...
+        for x in glob.iglob('%s/*' % path):
+            return False
+        for x in glob.iglob('%s/.*' % path):
+            return False
+        return True
+except (ImportError, AttributeError):
+    # Python ≤2.4
+    def is_emptydir(path):
+        # This will read the entire directory list to memory.
+        return not os.listdir(path)
 
 class WorkingCopy(object):
     def __init__(self, bdec, path, url):
@@ -107,7 +124,7 @@ class WorkingCopy(object):
 
     def _get_match(self, svnbin, env):
         ### quick little hack to auto-checkout missing working copies
-        if not os.path.isdir(self.path):
+        if not os.path.isdir(self.path) or is_emptydir(self.path):
             logging.info("autopopulate %s from %s" % (self.path, self.url))
             subprocess.check_call([svnbin, 'co', '-q',
                                    '--non-interactive',
@@ -132,7 +149,8 @@ class BigDoEverythingClasss(object):
         self.svnbin = config.get_value('svnbin')
         self.env = config.get_env()
         self.tracking = config.get_track()
-        self.worker = BackgroundWorker(self.svnbin, self.env)
+        self.hook = config.get_value('hook')
+        self.worker = BackgroundWorker(self.svnbin, self.env, self.hook)
         self.watch = [ ]
 
         self.hostports = [ ]
@@ -151,7 +169,7 @@ class BigDoEverythingClasss(object):
         # Add it to our watchers, and trigger an svn update.
         logging.info("Watching WC at %s <-> %s" % (wc.path, wc.url))
         self.watch.append(wc)
-        self.worker.add_work(OP_UPDATE, wc)
+        self.worker.add_work(OP_BOOT, wc)
 
     def _normalize_path(self, path):
         if path[0] != '/':
@@ -183,11 +201,12 @@ class BigDoEverythingClasss(object):
 
 # Start logging warnings if the work backlog reaches this many items
 BACKLOG_TOO_HIGH = 20
+OP_BOOT = 'boot'
 OP_UPDATE = 'update'
 OP_CLEANUP = 'cleanup'
 
 class BackgroundWorker(threading.Thread):
-    def __init__(self, svnbin, env):
+    def __init__(self, svnbin, env, hook):
         threading.Thread.__init__(self)
 
         # The main thread/process should not wait for this thread to exit.
@@ -196,6 +215,7 @@ class BackgroundWorker(threading.Thread)
 
         self.svnbin = svnbin
         self.env = env
+        self.hook = hook
         self.q = Queue.Queue()
 
         self.has_started = False
@@ -210,6 +230,8 @@ class BackgroundWorker(threading.Thread)
             try:
                 if operation == OP_UPDATE:
                     self._update(wc)
+                if operation == OP_BOOT:
+                    self._update(wc, boot=True)
                 elif operation == OP_CLEANUP:
                     self._cleanup(wc)
                 else:
@@ -229,7 +251,7 @@ class BackgroundWorker(threading.Thread)
 
         self.q.put((operation, wc))
 
-    def _update(self, wc):
+    def _update(self, wc, boot=False):
         "Update the specified working copy."
 
         # For giggles, let's clean up the working copy in case something
@@ -263,6 +285,12 @@ class BackgroundWorker(threading.Thread)
                 raise
         open(dotrevision, 'w').write(info['Revision'])
 
+        ## Run the hook
+        if self.hook:
+            args = [self.hook, ['post-update', 'boot'][boot],
+                    wc.path, info['Revision'], wc.url]
+            subprocess.check_call(args, env=self.env)
+
     def _cleanup(self, wc):
         "Run a cleanup on the specified working copy."