You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by as...@apache.org on 2012/11/24 21:29:48 UTC

svn commit: r1413258 [20/33] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/ notes/ notes/directory-index/ subversion/ subv...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db.h?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db.h Sat Nov 24 20:29:11 2012
@@ -255,7 +255,7 @@ typedef struct svn_wc__db_lock_t {
 */
 svn_error_t *
 svn_wc__db_open(svn_wc__db_t **db,
-                const svn_config_t *config,
+                svn_config_t *config,
                 svn_boolean_t auto_upgrade,
                 svn_boolean_t enforce_empty_wq,
                 apr_pool_t *result_pool,
@@ -370,7 +370,7 @@ svn_wc__db_get_wcroot(const char **wcroo
    In the BASE tree, each node corresponds to a particular node-rev in the
    repository.  It can be a mixed-revision tree.  Each node holds either a
    copy of the node-rev as it exists in the repository (if presence =
-   'normal'), or a place-holder (if presence = 'absent' or 'excluded' or
+   'normal'), or a place-holder (if presence = 'server-excluded' or 'excluded' or
    'not-present').
 
    @{
@@ -409,6 +409,10 @@ svn_wc__db_get_wcroot(const char **wcroo
    when the value of NEW_ACTUAL_PROPS matches NEW_PROPS, store NULL in
    ACTUAL, to mark the properties unmodified.
 
+   If NEW_IPROPS is not NULL, then it is a depth-first ordered array of
+   svn_prop_inherited_item_t * structures that is set as the base node's
+   inherited_properties.
+
    Any work items that are necessary as part of this node construction may
    be passed in WORK_ITEMS.
 
@@ -432,6 +436,7 @@ svn_wc__db_base_add_directory(svn_wc__db
                               const svn_skel_t *conflict,
                               svn_boolean_t update_actual_props,
                               apr_hash_t *new_actual_props,
+                              apr_array_header_t *new_iprops,
                               const svn_skel_t *work_items,
                               apr_pool_t *scratch_pool);
 
@@ -1036,6 +1041,7 @@ svn_wc__db_external_add_file(svn_wc__db_
                              svn_revnum_t revision,
 
                              const apr_hash_t *props,
+                             apr_array_header_t *iprops,
 
                              svn_revnum_t changed_rev,
                              apr_time_t changed_date,
@@ -1356,7 +1362,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t 
                            apr_pool_t *scratch_pool);
 
 
-/* ### do we need svn_wc__db_op_copy_absent() ??  */
+/* ### do we need svn_wc__db_op_copy_server_excluded() ??  */
 
 
 /* ### add a new versioned directory. a list of children is NOT passed
@@ -1923,7 +1929,7 @@ struct svn_wc__db_info_t {
   svn_boolean_t incomplete; /* TRUE if a working node is incomplete */
 
   const char *moved_to_abspath; /* Only on op-roots. See svn_wc_status3_t. */
-  svn_boolean_t moved_here;     /* On both op-roots and children. */
+  svn_boolean_t moved_here;     /* Only on op-roots. */
 
   svn_boolean_t file_external;
 };
@@ -2084,6 +2090,39 @@ svn_wc__db_read_pristine_props(apr_hash_
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
+/* Read a BASE node's inherited property information.
+
+   Set *IPROPS to to a depth-first ordered array of
+   svn_prop_inherited_item_t * structures representing the cached
+   inherited properties for the BASE node at LOCAL_ABSPATH.
+
+   If no cached properties are found, then set *IPROPS to NULL.
+   If LOCAL_ABSPATH represents the root of the repository, then set
+   *IPROPS to an empty array.
+
+   Allocate *IPROPS in RESULT_POOL, use SCRATCH_POOL for temporary
+   allocations. */
+svn_error_t *
+svn_wc__db_read_cached_iprops(apr_array_header_t **iprops,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
+/* Find BASE nodes with cached inherited properties.
+
+   Set *IPROPS_PATHS to a hash mapping const char * absolute working copy
+   paths to the same for each path in the working copy at or below
+   LOCAL_ABSPATH, limited by DEPTH, that has cached inherited properties
+   for the BASE node of the path.  Allocate *IPROP_PATHS in RESULT_POOL.
+   Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *
+svn_wc__db_get_children_with_cached_iprops(apr_hash_t **iprop_paths,
+                                           svn_depth_t depth,
+                                           const char *local_abspath,
+                                           svn_wc__db_t *db,
+                                           apr_pool_t *result_pool,
+                                           apr_pool_t *scratch_pool);
 
 /** Obtain a mapping of const char * local_abspaths to const svn_string_t*
  * property values in *VALUES, of all PROPNAME properties on LOCAL_ABSPATH
@@ -2396,6 +2435,12 @@ svn_wc__db_global_update(svn_wc__db_t *d
    EXCLUDE_RELPATHS is a hash containing const char *local_relpath.  Nodes
    for pathnames contained in EXCLUDE_RELPATHS are not touched by this
    function.  These pathnames should be paths relative to the wcroot.
+
+   If WCROOT_IPROPS is not NULL it is a hash mapping const char * absolute
+   working copy paths to depth-first ordered arrays of
+   svn_prop_inherited_item_t * structures.  If LOCAL_ABSPATH exists in
+   WCROOT_IPROPS, then set the hashed value as the node's inherited
+   properties.
 */
 svn_error_t *
 svn_wc__db_op_bump_revisions_post_update(svn_wc__db_t *db,
@@ -2406,6 +2451,7 @@ svn_wc__db_op_bump_revisions_post_update
                                          const char *new_repos_uuid,
                                          svn_revnum_t new_revision,
                                          apr_hash_t *exclude_relpaths,
+                                         apr_hash_t *wcroot_iprops,
                                          apr_pool_t *scratch_pool);
 
 
@@ -2747,6 +2793,23 @@ svn_wc__db_upgrade_get_repos_id(apr_int6
                                 const char *repos_root_url,
                                 apr_pool_t *scratch_pool);
 
+/* Upgrade the metadata concerning the WC at WCROOT_ABSPATH, in DB,
+ * to the SVN_WC__VERSION format.
+ *
+ * This function is used for upgrading wc-ng working copies to a newer
+ * wc-ng format. If a pre-1.7 working copy is found, this function
+ * returns SVN_ERR_WC_UPGRADE_REQUIRED.
+ *
+ * Upgrading subdirectories of a working copy is not supported.
+ * If WCROOT_ABSPATH is not a working copy root SVN_ERR_WC_INVALID_OP_ON_CWD
+ * is returned.
+ */
+svn_error_t *
+svn_wc__db_bump_format(int *result_format,
+                       const char *wcroot_abspath,
+                       svn_wc__db_t *db,
+                       apr_pool_t *scratch_pool);
+
 /* @} */
 
 
@@ -3136,6 +3199,21 @@ svn_wc__db_follow_moved_to(apr_array_hea
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool);
 
+/* Update a moved-away tree conflict victim at VICTIM_ABSPATH with changes
+ * brought in by the update operation which flagged the tree conflict.
+ * Set *WORK_ITEMS to a list of work items, allocated in RESULT_POOL, that
+ * need to run as part of marking the conflict resolved. */
+svn_error_t *
+svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
+                                             const char *victim_abspath,
+                                             svn_wc__db_t *db,
+                                             svn_wc_notify_func2_t notify_func,
+                                             void *notify_baton,
+                                             svn_cancel_func_t cancel_func,
+                                             void *cancel_baton,
+                                             apr_pool_t *result_pool,
+                                             apr_pool_t *scratch_pool);
+
 /* @} */
 
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_private.h?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_private.h Sat Nov 24 20:29:11 2012
@@ -36,7 +36,7 @@
 struct svn_wc__db_t {
   /* We need the config whenever we run into a new WC directory, in order
      to figure out where we should look for the corresponding datastore. */
-  const svn_config_t *config;
+  svn_config_t *config;
 
   /* Should we attempt to automatically upgrade the database when it is
      opened, and found to be not-current?  */
@@ -159,6 +159,24 @@ svn_wc__db_wcroot_parse_local_abspath(sv
 #define VERIFY_USABLE_WCROOT(wcroot)  SVN_ERR_ASSERT(               \
     (wcroot) != NULL && (wcroot)->format == SVN_WC__VERSION)
 
+/* Calculates the depth of the relpath below "" */
+APR_INLINE static int
+relpath_depth(const char *relpath)
+{
+  int n = 1;
+  if (*relpath == '\0')
+    return 0;
+
+  do
+  {
+    if (*relpath == '/')
+      n++;
+  }
+  while (*(++relpath));
+
+  return n;
+}
+
 
 /* */
 svn_error_t *
@@ -181,6 +199,7 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
                         const char *dir_abspath,
                         const char *sdb_fname,
                         svn_sqlite__mode_t smode,
+                        svn_boolean_t exclusive,
                         const char *const *my_statements,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool);
@@ -218,6 +237,50 @@ svn_wc__db_read_info_internal(svn_wc__db
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
 
+/* Like svn_wc__db_scan_deletion(), but with WCROOT+LOCAL_RELPATH instead of
+   DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
+svn_error_t *
+svn_wc__db_scan_deletion_internal(const char **base_del_relpath,
+                                  const char **moved_to_relpath,
+                                  const char **work_del_relpath,
+                                  const char **moved_to_op_root_relpath,
+                                  svn_wc__db_wcroot_t *wcroot,
+                                  const char *local_relpath,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
+
+/* Like svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH instead of
+   DB+LOCAL_ABSPATH and outputting REPOS_ID instead of URL+UUID. */
+svn_error_t *
+svn_wc__db_base_get_info_internal(svn_wc__db_status_t *status,
+                                  svn_kind_t *kind,
+                                  svn_revnum_t *revision,
+                                  const char **repos_relpath,
+                                  apr_int64_t *repos_id,
+                                  svn_revnum_t *changed_rev,
+                                  apr_time_t *changed_date,
+                                  const char **changed_author,
+                                  svn_depth_t *depth,
+                                  const svn_checksum_t **checksum,
+                                  const char **target,
+                                  svn_wc__db_lock_t **lock,
+                                  svn_boolean_t *had_props,
+                                  svn_boolean_t *update_root,
+                                  svn_wc__db_wcroot_t *wcroot,
+                                  const char *local_relpath,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
+
+
+/* Like svn_wc__db_read_conflict(), but with WCROOT+LOCAL_RELPATH instead of
+   DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
+svn_error_t *
+svn_wc__db_read_conflict_internal(svn_skel_t **conflict,
+                                  svn_wc__db_wcroot_t *wcroot,
+                                  const char *local_relpath,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
+
 
 /* Transaction handling */
 

Added: subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_update_move.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_update_move.c (added)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_update_move.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,739 @@
+/*
+ * wc_db_update_move.c :  updating moves during tree-conflict resolution
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* This editor is used during resolution of tree conflicts.
+ *
+ * An operation such as update can produce incoming changes for a
+ * locally moved-away subtree, causing a tree-conflict to be flagged.
+ * This editor transfers these changes from the moved-away part of the
+ * working copy to the corresponding moved-here part of the working copy.
+ *
+ * Both the driver and receiver components of the editor are implemented
+ * in this file.
+ */
+
+#define SVN_WC__I_AM_WC_DB
+
+#include "svn_checksum.h"
+#include "svn_dirent_uri.h"
+#include "svn_editor.h"
+#include "svn_error.h"
+#include "svn_wc.h"
+#include "svn_pools.h"
+
+#include "private/svn_skel.h"
+#include "private/svn_sqlite.h"
+#include "private/svn_wc_private.h"
+
+#include "wc.h"
+#include "wc_db_private.h"
+#include "conflicts.h"
+#include "workqueue.h"
+
+/*
+ * Receiver code.
+ */
+
+struct tc_editor_baton {
+  const char *src_relpath;
+  const char *dst_relpath;
+  svn_wc__db_t *db;
+  svn_wc__db_wcroot_t *wcroot;
+  svn_skel_t **work_items;
+  svn_wc_conflict_version_t *old_version;
+  svn_wc_conflict_version_t *new_version;
+  svn_wc_notify_func2_t notify_func;
+  void *notify_baton;
+  apr_pool_t *result_pool;
+};
+
+static svn_error_t *
+tc_editor_add_directory(void *baton,
+                        const char *relpath,
+                        const apr_array_header_t *children,
+                        apr_hash_t *props,
+                        svn_revnum_t replaces_rev,
+                        apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_add_file(void *baton,
+                   const char *relpath,
+                   const svn_checksum_t *checksum,
+                   svn_stream_t *contents,
+                   apr_hash_t *props,
+                   svn_revnum_t replaces_rev,
+                   apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_add_symlink(void *baton,
+                      const char *relpath,
+                      const char *target,
+                      apr_hash_t *props,
+                      svn_revnum_t replaces_rev,
+                      apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_add_absent(void *baton,
+                     const char *relpath,
+                     svn_kind_t kind,
+                     svn_revnum_t replaces_rev,
+                     apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_alter_directory(void *baton,
+                          const char *relpath,
+                          svn_revnum_t revision,
+                          const apr_array_header_t *children,
+                          apr_hash_t *props,
+                          apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_alter_file(void *baton,
+                     const char *dst_relpath,
+                     svn_revnum_t expected_moved_here_revision,
+                     apr_hash_t *props,
+                     const svn_checksum_t *moved_away_checksum,
+                     svn_stream_t *post_update_contents,
+                     apr_pool_t *scratch_pool)
+{
+  struct tc_editor_baton *b = baton;
+  const svn_checksum_t *moved_here_checksum;
+  const char *original_repos_relpath;
+  svn_revnum_t original_revision;
+  svn_kind_t kind;
+
+  /* Get kind, revision, and checksum of the moved-here node. */
+  /* 
+   * ### Currently doesn't work right if the moved-away node has been replaced.
+   * ### Need to read info from the move op-root's op-depth, not WORKING, to
+   * ### properly update shadowed nodes within multi-layer move destinations.
+   */
+  SVN_ERR(svn_wc__db_read_info_internal(NULL, &kind, NULL, NULL, NULL, NULL,
+                                        NULL, NULL, NULL, &moved_here_checksum,
+                                        NULL, &original_repos_relpath, NULL,
+                                        &original_revision, NULL, NULL, NULL,
+                                        NULL, NULL, NULL, NULL, NULL, NULL,
+                                        NULL, NULL, b->wcroot, dst_relpath,
+                                        scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(original_revision == expected_moved_here_revision);
+
+  /* ### check original revision against moved-here op-root revision? */
+  if (kind != svn_kind_file)
+    return SVN_NO_ERROR;
+
+  /* ### what if checksum kind differs?*/
+  if (!svn_checksum_match(moved_away_checksum, moved_here_checksum))
+    {
+      const char *moved_to_abspath = svn_dirent_join(b->wcroot->abspath,
+                                                     dst_relpath,
+                                                     scratch_pool);
+      const char *pre_update_pristine_abspath;
+      const char *post_update_pristine_abspath;
+      svn_skel_t *conflict_skel;
+      enum svn_wc_merge_outcome_t merge_outcome;
+      svn_wc_notify_state_t content_state;
+      svn_wc_notify_t *notify;
+
+      /*
+       * Run a 3-way merge to update the file, using the pre-update
+       * pristine text as the merge base, the post-update pristine
+       * text as the merge-left version, and the current content of the
+       * moved-here working file as the merge-right version.
+       */
+      SVN_ERR(svn_wc__db_pristine_get_path(&pre_update_pristine_abspath,
+                                           b->db, moved_to_abspath,
+                                           moved_here_checksum,
+                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_pristine_get_path(&post_update_pristine_abspath,
+                                           b->db, moved_to_abspath,
+                                           moved_away_checksum,
+                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__internal_merge(b->work_items, &conflict_skel,
+                                     &merge_outcome, b->db,
+                                     pre_update_pristine_abspath,
+                                     post_update_pristine_abspath,
+                                     moved_to_abspath,
+                                     moved_to_abspath,
+                                     NULL, NULL, NULL, /* diff labels */
+                                     NULL, /* actual props */
+                                     FALSE, /* dry-run */
+                                     NULL, /* diff3-cmd */
+                                     NULL, /* merge options */
+                                     NULL, /* prop_diff */
+                                     NULL, NULL, /* cancel_func + baton */
+                                     b->result_pool, scratch_pool));
+
+      if (merge_outcome == svn_wc_merge_conflict)
+        {
+          svn_skel_t *work_item;
+          svn_wc_conflict_version_t *original_version;
+
+          if (conflict_skel)
+            {
+              original_version = svn_wc_conflict_version_dup(b->old_version,
+                                                             scratch_pool);
+              original_version->path_in_repos = original_repos_relpath;
+              original_version->node_kind = svn_node_file;
+              SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel,
+                                                          original_version,
+                                                          scratch_pool,
+                                                          scratch_pool));
+              SVN_ERR(svn_wc__conflict_create_markers(&work_item, b->db,
+                                                      moved_to_abspath,
+                                                      conflict_skel,
+                                                      scratch_pool,
+                                                      scratch_pool));
+              *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
+                                                b->result_pool);
+            }
+          content_state = svn_wc_notify_state_conflicted;
+        }
+      else
+        {
+          svn_boolean_t is_locally_modified;
+
+          SVN_ERR(svn_wc__internal_file_modified_p(&is_locally_modified,
+                                                   b->db, moved_to_abspath,
+                                                   FALSE /* exact_comparison */,
+                                                   scratch_pool));
+          if (is_locally_modified)
+            content_state = svn_wc_notify_state_merged;
+          else
+            content_state = svn_wc_notify_state_changed;
+        }
+
+      notify = svn_wc_create_notify(moved_to_abspath,
+                                    svn_wc_notify_update_update,
+                                    scratch_pool);
+      notify->kind = svn_node_file;
+      notify->content_state = content_state;
+      notify->prop_state = svn_wc_notify_state_unknown; /* ### TODO */
+      notify->old_revision = b->old_version->peg_rev;
+      notify->revision = b->new_version->peg_rev;
+      b->notify_func(b->notify_baton, notify, scratch_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_alter_symlink(void *baton,
+                        const char *relpath,
+                        svn_revnum_t revision,
+                        apr_hash_t *props,
+                        const char *target,
+                        apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_delete(void *baton,
+                 const char *relpath,
+                 svn_revnum_t revision,
+                 apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_copy(void *baton,
+               const char *src_relpath,
+               svn_revnum_t src_revision,
+               const char *dst_relpath,
+               svn_revnum_t replaces_rev,
+               apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_move(void *baton,
+               const char *src_relpath,
+               svn_revnum_t src_revision,
+               const char *dst_relpath,
+               svn_revnum_t replaces_rev,
+               apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_rotate(void *baton,
+                 const apr_array_header_t *relpaths,
+                 const apr_array_header_t *revisions,
+                 apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
+}
+
+static svn_error_t *
+tc_editor_complete(void *baton,
+                   apr_pool_t *scratch_pool)
+{
+  struct tc_editor_baton *b = baton;
+  svn_wc_notify_t *notify;
+
+  notify = svn_wc_create_notify(svn_dirent_join(b->wcroot->abspath,
+                                                b->dst_relpath,
+                                                scratch_pool),
+                                svn_wc_notify_update_completed,
+                                scratch_pool);
+  notify->kind = svn_node_none;
+  notify->content_state = svn_wc_notify_state_inapplicable;
+  notify->prop_state = svn_wc_notify_state_inapplicable;
+  notify->revision = b->new_version->peg_rev;
+  b->notify_func(b->notify_baton, notify, scratch_pool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tc_editor_abort(void *baton,
+                apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static const svn_editor_cb_many_t editor_ops = {
+  tc_editor_add_directory,
+  tc_editor_add_file,
+  tc_editor_add_symlink,
+  tc_editor_add_absent,
+  tc_editor_alter_directory,
+  tc_editor_alter_file,
+  tc_editor_alter_symlink,
+  tc_editor_delete,
+  tc_editor_copy,
+  tc_editor_move,
+  tc_editor_rotate,
+  tc_editor_complete,
+  tc_editor_abort
+};
+
+
+/*
+ * Driver code.
+ */
+
+static svn_error_t *
+get_tc_info(svn_wc_operation_t *operation,
+            svn_wc_conflict_reason_t *local_change,
+            svn_wc_conflict_action_t *incoming_change,
+            svn_wc_conflict_version_t **old_version,
+            svn_wc_conflict_version_t **new_version,
+            const char *src_abspath,
+            svn_wc__db_t *db,
+            apr_pool_t *result_pool,
+            apr_pool_t *scratch_pool)
+{
+  const apr_array_header_t *locations;
+  svn_boolean_t tree_conflicted;
+  svn_skel_t *conflict_skel;
+  svn_kind_t kind;
+
+  /* ### Check for mixed-rev src or dst? */
+
+  /* Check for tree conflict on src. */
+  SVN_ERR(svn_wc__db_read_conflict(&conflict_skel, db,
+                                   src_abspath,
+                                   scratch_pool, scratch_pool));
+  if (!conflict_skel)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                             _("'%s' is not in conflict"),
+                             svn_dirent_local_style(src_abspath,
+                                                    scratch_pool));
+
+  SVN_ERR(svn_wc__conflict_read_info(operation, &locations,
+                                     NULL, NULL, &tree_conflicted,
+                                     db, src_abspath,
+                                     conflict_skel, result_pool,
+                                     scratch_pool));
+  if (!tree_conflicted)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                             _("'%s' is not a tree-conflict victim"),
+                             svn_dirent_local_style(src_abspath,
+                                                    scratch_pool));
+  if (locations)
+    {
+      *old_version = APR_ARRAY_IDX(locations, 0,
+                                     svn_wc_conflict_version_t *);
+      if (locations->nelts > 1)
+        *new_version = APR_ARRAY_IDX(locations, 1,
+                                     svn_wc_conflict_version_t *);
+      else
+        {
+          const char *repos_root_url;
+          const char *repos_uuid;
+          const char *repos_relpath;
+          svn_revnum_t revision;
+          svn_node_kind_t node_kind;
+
+          /* Construct b->new_version from BASE info. */
+          SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
+                                           &repos_relpath, &repos_root_url,
+                                           &repos_uuid, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL, NULL,
+                                           db, src_abspath, result_pool,
+                                           scratch_pool));
+          node_kind = svn__node_kind_from_kind(kind);
+          *new_version = svn_wc_conflict_version_create2(repos_root_url,
+                                                         repos_uuid,
+                                                         repos_relpath,
+                                                         revision,
+                                                         node_kind,
+                                                         scratch_pool);
+        }
+    }
+
+  SVN_ERR(svn_wc__conflict_read_tree_conflict(local_change,
+                                              incoming_change,
+                                              db, src_abspath,
+                                              conflict_skel, scratch_pool,
+                                              scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_moved_away_file(svn_editor_t *tc_editor,
+                       const char *src_relpath,
+                       const char *dst_relpath,
+                       const char *move_dst_op_root_relpath,
+                       svn_revnum_t move_dst_op_root_revision,
+                       svn_wc__db_t *db,
+                       svn_wc__db_wcroot_t *wcroot,
+                       apr_pool_t *scratch_pool)
+{
+  svn_kind_t kind;
+  svn_stream_t *post_update_contents;
+  const svn_checksum_t *moved_away_checksum;
+                    
+  /* Read post-update contents from the updated moved-away file and tell
+   * the editor to merge them into the moved-here file. */
+  SVN_ERR(svn_wc__db_read_pristine_info(NULL, &kind, NULL, NULL, NULL, NULL,
+                                        &moved_away_checksum, NULL, NULL, db,
+                                        svn_dirent_join(wcroot->abspath,
+                                                        src_relpath,
+                                                        scratch_pool),
+                                        scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_pristine_read(&post_update_contents, NULL, db,
+                                   wcroot->abspath, moved_away_checksum,
+                                   scratch_pool, scratch_pool));
+  SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
+                                move_dst_op_root_revision,
+                                NULL, /* ### TODO props */
+                                moved_away_checksum,
+                                post_update_contents));
+  SVN_ERR(svn_stream_close(post_update_contents));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_moved_away_dir(svn_editor_t *tc_editor,
+                      const char *src_relpath,
+                      const char *dst_relpath,
+                      const char *move_dst_op_root_relpath,
+                      svn_revnum_t move_dst_op_root_revision,
+                      svn_wc__db_t *db,
+                      svn_wc__db_wcroot_t *wcroot,
+                      apr_pool_t *scratch_pool)
+{
+  /* ### notify */
+
+  /* ### update prop content if changed */
+
+  /* ### update list of children if changed */
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+update_moved_away_subtree(svn_editor_t *tc_editor,
+                          const char *src_relpath,
+                          const char *dst_relpath,
+                          const char *move_dst_op_root_relpath,
+                          svn_revnum_t move_dst_op_root_revision,
+                          svn_wc__db_t *db,
+                          svn_wc__db_wcroot_t *wcroot,
+                          apr_pool_t *scratch_pool)
+{
+  const apr_array_header_t *children;
+  apr_pool_t *iterpool;
+  int i;
+
+  SVN_ERR(update_moved_away_dir(tc_editor, src_relpath, dst_relpath,
+                                move_dst_op_root_relpath,
+                                move_dst_op_root_revision,
+                                db, wcroot, scratch_pool));
+
+  SVN_ERR(svn_wc__db_base_get_children(&children, db,
+                                       svn_dirent_join(wcroot->abspath,
+                                                       src_relpath,
+                                                       scratch_pool),
+                                       scratch_pool, scratch_pool));
+  iterpool = svn_pool_create(scratch_pool);
+  for (i = 0; i < children->nelts; i++)
+    {
+      const char *child_src_relpath;
+      svn_kind_t child_kind;
+      const char *child_dst_op_root_relpath;
+      const char *child_dst_relpath;
+
+      svn_pool_clear(iterpool);
+
+      child_src_relpath = svn_relpath_join(src_relpath,
+                                           APR_ARRAY_IDX(children, i,
+                                                         const char *),
+                                           iterpool);
+
+      /* Is this child part of our move operation? */
+      /* ### need to handle children which were newly added or removed
+       * ### during the update */
+      SVN_ERR(svn_wc__db_scan_deletion_internal(NULL, &child_dst_relpath, NULL,
+                                                &child_dst_op_root_relpath,
+                                                wcroot, child_src_relpath,
+                                                iterpool, iterpool));
+      if (child_dst_op_root_relpath == NULL ||
+          strcmp(child_dst_op_root_relpath, move_dst_op_root_relpath) != 0)
+        continue;
+
+      SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &child_kind,
+                                                NULL, NULL, NULL, NULL,
+                                                NULL, NULL, NULL, NULL,
+                                                NULL, NULL, NULL, NULL,
+                                                wcroot, child_src_relpath,
+                                                iterpool, iterpool));
+
+      if (child_kind == svn_kind_file || child_kind == svn_kind_symlink)
+        SVN_ERR(update_moved_away_file(tc_editor, child_src_relpath,
+                                       child_dst_relpath,
+                                       move_dst_op_root_relpath,
+                                       move_dst_op_root_revision,
+                                       db, wcroot, iterpool));
+      else if (child_kind == svn_kind_dir)
+        SVN_ERR(update_moved_away_subtree(tc_editor, child_src_relpath,
+                                          child_dst_relpath,
+                                          move_dst_op_root_relpath,
+                                          move_dst_op_root_revision,
+                                          db, wcroot, iterpool));
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+drive_tree_conflict_editor(svn_editor_t *tc_editor,
+                           const char *src_relpath,
+                           const char *dst_relpath,
+                           svn_wc_operation_t operation,
+                           svn_wc_conflict_reason_t local_change,
+                           svn_wc_conflict_action_t incoming_change,
+                           svn_wc_conflict_version_t *old_version,
+                           svn_wc_conflict_version_t *new_version,
+                           svn_wc__db_t *db,
+                           svn_wc__db_wcroot_t *wcroot,
+                           svn_cancel_func_t cancel_func,
+                           void *cancel_baton,
+                           apr_pool_t *scratch_pool)
+{
+  /*
+   * Refuse to auto-resolve unsupported tree conflicts.
+   */
+  /* ### Only handle conflicts created by update/switch operations for now. */
+  if (operation != svn_wc_operation_update &&
+      operation != svn_wc_operation_switch)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                            _("Cannot auto-resolve tree-conflict on '%s'"),
+                            svn_dirent_local_style(
+                              svn_dirent_join(wcroot->abspath,
+                                              src_relpath, scratch_pool),
+                              scratch_pool));
+
+  /*
+   * Drive the TC editor to transfer incoming changes from the move source
+   * to the move destination.
+   *
+   * The pre-update tree is within dst at the op-depth of the move's op-root.
+   * The post-update base tree is within src at op-depth zero.
+   *
+   * We walk the move source (i.e. the post-update tree), comparing each node
+   * with the equivalent node at the move destination and applying the update
+   * to nodes at the move destination.
+   */
+  if (old_version->node_kind == svn_node_file)
+    SVN_ERR(update_moved_away_file(tc_editor, src_relpath, dst_relpath,
+                                   dst_relpath, old_version->peg_rev,
+                                   db, wcroot, scratch_pool));
+  else if (old_version->node_kind == svn_node_dir)
+    SVN_ERR(update_moved_away_subtree(tc_editor, src_relpath, dst_relpath,
+                                      dst_relpath, old_version->peg_rev,
+                                      db, wcroot, scratch_pool));
+
+  SVN_ERR(svn_editor_complete(tc_editor));
+
+  return SVN_NO_ERROR;
+}
+
+struct update_moved_away_conflict_victim_baton {
+  svn_skel_t **work_items;
+  const char *victim_relpath;
+  svn_wc_operation_t operation;
+  svn_wc_conflict_reason_t local_change;
+  svn_wc_conflict_action_t incoming_change;
+  svn_wc_conflict_version_t *old_version;
+  svn_wc_conflict_version_t *new_version;
+  svn_wc__db_t *db;
+  svn_wc_notify_func2_t notify_func;
+  void *notify_baton;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+  apr_pool_t *result_pool;
+};
+
+/* An implementation of svn_wc__db_txn_callback_t. */
+static svn_error_t *
+update_moved_away_conflict_victim(void *baton,
+                                  svn_wc__db_wcroot_t *wcroot,
+                                  const char *victim_relpath,
+                                  apr_pool_t *scratch_pool)
+{
+  struct update_moved_away_conflict_victim_baton *b = baton;
+  svn_editor_t *tc_editor;
+  struct tc_editor_baton *tc_editor_baton;
+
+  /* ### assumes wc write lock already held */
+
+  /* Construct editor baton. */
+  tc_editor_baton = apr_pcalloc(scratch_pool, sizeof(*tc_editor_baton));
+  tc_editor_baton->src_relpath = b->victim_relpath;
+  SVN_ERR(svn_wc__db_scan_deletion_internal(NULL,
+                                            &tc_editor_baton->dst_relpath,
+                                            NULL, NULL, wcroot,
+                                            tc_editor_baton->src_relpath,
+                                            scratch_pool, scratch_pool));
+  if (tc_editor_baton->dst_relpath == NULL)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                             _("The node '%s' has not been moved away"),
+                             svn_dirent_local_style(
+                               svn_dirent_join(wcroot->abspath,
+                                               b->victim_relpath,
+                                               scratch_pool),
+                               scratch_pool));
+  tc_editor_baton->old_version= b->old_version;
+  tc_editor_baton->new_version= b->new_version;
+  tc_editor_baton->db = b->db;
+  tc_editor_baton->wcroot = wcroot;
+  tc_editor_baton->work_items = b->work_items;
+  tc_editor_baton->notify_func = b->notify_func;
+  tc_editor_baton->notify_baton = b->notify_baton;
+  tc_editor_baton->result_pool = b->result_pool;
+
+  /* Create the editor... */
+  SVN_ERR(svn_editor_create(&tc_editor, tc_editor_baton,
+                            b->cancel_func, b->cancel_baton,
+                            scratch_pool, scratch_pool));
+  SVN_ERR(svn_editor_setcb_many(tc_editor, &editor_ops, scratch_pool));
+
+  /* ... and drive it. */
+  SVN_ERR(drive_tree_conflict_editor(tc_editor,
+                                     tc_editor_baton->src_relpath,
+                                     tc_editor_baton->dst_relpath,
+                                     b->operation,
+                                     b->local_change, b->incoming_change,
+                                     tc_editor_baton->old_version,
+                                     tc_editor_baton->new_version,
+                                     b->db, wcroot,
+                                     b->cancel_func, b->cancel_baton,
+                                     scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
+                                             const char *victim_abspath,
+                                             svn_wc__db_t *db,
+                                             svn_wc_notify_func2_t notify_func,
+                                             void *notify_baton,
+                                             svn_cancel_func_t cancel_func,
+                                             void *cancel_baton,
+                                             apr_pool_t *result_pool,
+                                             apr_pool_t *scratch_pool)
+{
+  struct update_moved_away_conflict_victim_baton b;
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  svn_wc_operation_t operation;
+  svn_wc_conflict_reason_t local_change;
+  svn_wc_conflict_action_t incoming_change;
+  svn_wc_conflict_version_t *old_version;
+  svn_wc_conflict_version_t *new_version;
+
+  SVN_ERR(get_tc_info(&operation, &local_change, &incoming_change,
+                      &old_version, &new_version,
+                      victim_abspath, db, scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+                                                db, victim_abspath,
+                                                scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  b.work_items = work_items;
+  b.victim_relpath = local_relpath;
+  b.operation = operation;
+  b.local_change = local_change;
+  b.incoming_change = incoming_change;
+  b.old_version = old_version;
+  b.new_version = new_version;
+  b.db = db;
+  b.notify_func = notify_func;
+  b.notify_baton = notify_baton;
+  b.cancel_func = cancel_func;
+  b.cancel_baton = cancel_baton;
+  b.result_pool = result_pool;
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath,
+                              update_moved_away_conflict_victim, &b,
+                              scratch_pool));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_util.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_util.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_util.c Sat Nov 24 20:29:11 2012
@@ -80,10 +80,10 @@ svn_wc__db_util_fetch_wc_id(apr_int64_t 
 /* An SQLite application defined function that allows SQL queries to
    use "relpath_depth(local_relpath)".  */
 static svn_error_t *
-relpath_depth(svn_sqlite__context_t *sctx,
-              int argc,
-              svn_sqlite__value_t *values[],
-              apr_pool_t *scratch_pool)
+relpath_depth_sqlite(svn_sqlite__context_t *sctx,
+                     int argc,
+                     svn_sqlite__value_t *values[],
+                     apr_pool_t *scratch_pool)
 {
   const char *path = NULL;
   apr_int64_t depth;
@@ -114,6 +114,7 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
                         const char *dir_abspath,
                         const char *sdb_fname,
                         svn_sqlite__mode_t smode,
+                        svn_boolean_t exclusive,
                         const char *const *my_statements,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool)
@@ -140,8 +141,11 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
                            my_statements ? my_statements : statements,
                            0, NULL, result_pool, scratch_pool));
 
+  if (exclusive)
+    SVN_ERR(svn_sqlite__exec_statements(*sdb, STMT_PRAGMA_LOCKING_MODE));
+
   SVN_ERR(svn_sqlite__create_scalar_function(*sdb, "relpath_depth", 1,
-                                             relpath_depth, NULL));
+                                             relpath_depth_sqlite, NULL));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_wcroot.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_wcroot.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/wc_db_wcroot.c Sat Nov 24 20:29:11 2012
@@ -26,6 +26,8 @@
 #include <assert.h>
 
 #include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_version.h"
 
 #include "wc.h"
 #include "adm_files.h"
@@ -182,7 +184,7 @@ close_wcroot(void *data)
       svn_error_clear(err_pdb);
       return result;
     }
-  
+
   if (err_sdb)
     {
       apr_status_t result = err_sdb->apr_err;
@@ -196,7 +198,7 @@ close_wcroot(void *data)
 
 svn_error_t *
 svn_wc__db_open(svn_wc__db_t **db,
-                const svn_config_t *config,
+                svn_config_t *config,
                 svn_boolean_t auto_upgrade,
                 svn_boolean_t enforce_empty_wq,
                 apr_pool_t *result_pool,
@@ -305,9 +307,24 @@ svn_wc__db_pdh_create_wcroot(svn_wc__db_
     }
 
   /* Auto-upgrade the SDB if possible.  */
-  if (format < SVN_WC__VERSION && auto_upgrade)
-    SVN_ERR(svn_wc__upgrade_sdb(&format, wcroot_abspath, sdb, format,
-                                scratch_pool));
+  if (format < SVN_WC__VERSION)
+    {
+      if (auto_upgrade)
+        {
+          if (format >= SVN_WC__WC_NG_VERSION)
+            SVN_ERR(svn_wc__upgrade_sdb(&format, wcroot_abspath, sdb, format,
+                                        scratch_pool));
+        }
+      else
+        return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL,
+                                 _("The working copy at '%s'\nis too old "
+                                   "(format %d) to work with client version "
+                                   "'%s' (expects format %d). You need to "
+                                   "upgrade the working copy first.\n"),
+                                   svn_dirent_local_style(wcroot_abspath,
+                                   scratch_pool), format, SVN_VERSION,
+                                   SVN_WC__VERSION);
+    }
 
   *wcroot = apr_palloc(result_pool, sizeof(**wcroot));
 
@@ -366,6 +383,40 @@ compute_relpath(const svn_wc__db_wcroot_
 }
 
 
+/* Return in *LINK_TARGET_ABSPATH the absolute path the symlink at
+ * LOCAL_ABSPATH is pointing to. Perform all allocations in POOL. */
+static svn_error_t *
+read_link_target(const char **link_target_abspath,
+                 const char *local_abspath,
+                 apr_pool_t *pool)
+{
+  svn_string_t *link_target;
+  const char *canon_link_target;
+
+  SVN_ERR(svn_io_read_link(&link_target, local_abspath, pool));
+  if (link_target->len == 0)
+    return svn_error_createf(SVN_ERR_WC_NOT_SYMLINK, NULL,
+                             _("The symlink at '%s' points nowhere"),
+                             svn_dirent_local_style(local_abspath, pool));
+
+  canon_link_target = svn_dirent_canonicalize(link_target->data, pool);
+
+  /* Treat relative symlinks as relative to LOCAL_ABSPATH's parent. */
+  if (!svn_dirent_is_absolute(canon_link_target))
+    canon_link_target = svn_dirent_join(svn_dirent_dirname(local_abspath,
+                                                           pool),
+                                        canon_link_target, pool);
+
+  /* Collapse any .. in the symlink part of the path. */
+  if (svn_path_is_backpath_present(canon_link_target))
+    SVN_ERR(svn_dirent_get_absolute(link_target_abspath, canon_link_target,
+                                    pool));
+  else
+    *link_target_abspath = canon_link_target;
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot,
                                       const char **local_relpath,
@@ -487,6 +538,18 @@ svn_wc__db_wcroot_parse_local_abspath(sv
 
       if (adm_subdir_kind == svn_node_dir)
         {
+          svn_boolean_t sqlite_exclusive = FALSE;
+
+          err = svn_config_get_bool(db->config, &sqlite_exclusive,
+                                    SVN_CONFIG_SECTION_WORKING_COPY,
+                                    SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE,
+                                    FALSE);
+          if (err)
+            {
+              svn_error_clear(err);
+              sqlite_exclusive = FALSE;
+            }
+
           /* We always open the database in read/write mode.  If the database
              isn't writable in the filesystem, SQLite will internally open
              it as read-only, and we'll get an error if we try to do a write
@@ -496,7 +559,8 @@ svn_wc__db_wcroot_parse_local_abspath(sv
              we're caching database handles, it make sense to be as permissive
              as the filesystem allows. */
           err = svn_wc__db_util_open_db(&sdb, local_abspath, SDB_FILE,
-                                        svn_sqlite__mode_readwrite, NULL,
+                                        svn_sqlite__mode_readwrite,
+                                        sqlite_exclusive, NULL,
                                         db->state_pool, scratch_pool);
           if (err == NULL)
             {
@@ -563,6 +627,8 @@ svn_wc__db_wcroot_parse_local_abspath(sv
                   if (found_wcroot)
                     break;
 
+                  SVN_ERR(read_link_target(&local_abspath, local_abspath,
+                                           scratch_pool));
 try_symlink_as_dir:
                   kind = svn_kind_dir;
                   moved_upwards = FALSE;
@@ -619,32 +685,45 @@ try_symlink_as_dir:
          inside the wcroot, but we know the abspath is this directory
          (ie. where we found it).  */
 
-      SVN_ERR(svn_wc__db_pdh_create_wcroot(wcroot,
+      err = svn_wc__db_pdh_create_wcroot(wcroot,
                             apr_pstrdup(db->state_pool, local_abspath),
                             sdb, pdb, wc_id, FORMAT_FROM_SDB,
                             db->auto_upgrade, db->enforce_empty_wq,
-                            db->state_pool, scratch_pool));
+                            db->state_pool, scratch_pool);
+      if (err && (err->apr_err == SVN_ERR_WC_UNSUPPORTED_FORMAT ||
+                  err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED) &&
+          kind == svn_kind_symlink)
+        {
+          /* We found an unsupported WC after traversing upwards from a
+           * symlink. Fall through to code below to check if the symlink
+           * points at a supported WC. */
+          svn_error_clear(err);
+          *wcroot = NULL;
+        }
+      else
+        SVN_ERR(err);
     }
   else
     {
       /* We found a wc-1 working copy directory.  */
       SVN_ERR(svn_wc__db_pdh_create_wcroot(wcroot,
                             apr_pstrdup(db->state_pool, local_abspath),
-                            NULL, NULL, UNKNOWN_WC_ID, wc_format,
+                            NULL, UNKNOWN_WC_ID, wc_format,
                             db->auto_upgrade, db->enforce_empty_wq,
                             db->state_pool, scratch_pool));
     }
 
-  {
-    const char *dir_relpath;
+  if (*wcroot)
+    {
+      const char *dir_relpath;
 
-    /* The subdirectory's relpath is easily computed relative to the
-       wcroot that we just found.  */
-    dir_relpath = compute_relpath(*wcroot, local_dir_abspath, NULL);
-
-    /* And the result local_relpath may include a filename.  */
-    *local_relpath = svn_relpath_join(dir_relpath, build_relpath, result_pool);
-  }
+      /* The subdirectory's relpath is easily computed relative to the
+         wcroot that we just found.  */
+      dir_relpath = compute_relpath(*wcroot, local_dir_abspath, NULL);
+
+      /* And the result local_relpath may include a filename.  */
+      *local_relpath = svn_relpath_join(dir_relpath, build_relpath, result_pool);
+    }
 
   if (kind == svn_kind_symlink)
     {
@@ -658,33 +737,38 @@ try_symlink_as_dir:
        * points to a directory, try to find a wcroot in that directory
        * instead. */
 
-      err = svn_wc__db_read_info_internal(&status, NULL, NULL, NULL, NULL,
-                                          NULL, NULL, NULL, NULL, NULL, NULL,
-                                          NULL, NULL, NULL, NULL, NULL, NULL,
-                                          NULL, &conflicted, NULL, NULL, NULL,
-                                          NULL, NULL, NULL,
-                                          *wcroot, *local_relpath,
-                                          scratch_pool, scratch_pool);
-      if (err)
+      if (*wcroot)
         {
-          if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
-              && !SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
-            return svn_error_trace(err);
+          err = svn_wc__db_read_info_internal(&status, NULL, NULL, NULL, NULL,
+                                              NULL, NULL, NULL, NULL, NULL,
+                                              NULL, NULL, NULL, NULL, NULL,
+                                              NULL, NULL, NULL, &conflicted,
+                                              NULL, NULL, NULL, NULL, NULL,
+                                              NULL, *wcroot, *local_relpath,
+                                              scratch_pool, scratch_pool);
+          if (err)
+            {
+              if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
+                  && !SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
+                return svn_error_trace(err);
 
-          svn_error_clear(err);
-          retry_if_dir = TRUE; /* The symlink is unversioned. */
+              svn_error_clear(err);
+              retry_if_dir = TRUE; /* The symlink is unversioned. */
+            }
+          else
+            {
+              /* The symlink is versioned, or obstructs a versioned node.
+               * Ignore non-conflicted not-present/excluded nodes.
+               * This allows the symlink to redirect the wcroot query to a
+               * directory, regardless of 'invisible' nodes in this WC. */
+              retry_if_dir = ((status == svn_wc__db_status_not_present ||
+                               status == svn_wc__db_status_excluded ||
+                               status == svn_wc__db_status_server_excluded)
+                              && !conflicted);
+            }
         }
       else
-        {
-          /* The symlink is versioned, or obstructs a versioned node.
-           * Ignore non-conflicted not-present/excluded nodes.
-           * This allows the symlink to redirect the wcroot query to a
-           * directory, regardless of 'invisible' nodes in this WC. */
-          retry_if_dir = ((status == svn_wc__db_status_not_present ||
-                           status == svn_wc__db_status_excluded ||
-                           status == svn_wc__db_status_server_excluded)
-                          && !conflicted);
-        }
+        retry_if_dir = TRUE;
 
       if (retry_if_dir)
         {
@@ -695,7 +779,11 @@ try_symlink_as_dir:
                                              scratch_pool));
           if (resolved_kind == svn_node_dir)
             {
-              local_abspath = original_abspath;
+              SVN_ERR(read_link_target(&local_abspath, original_abspath,
+                                       scratch_pool));
+              /* This handle was opened in this function but is not going
+                 to be used further so close it. */
+              SVN_ERR(svn_sqlite__close(sdb));
               goto try_symlink_as_dir;
             }
         }

Modified: subversion/branches/compressed-pristines/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_authz_svn/mod_authz_svn.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/compressed-pristines/subversion/mod_authz_svn/mod_authz_svn.c Sat Nov 24 20:29:11 2012
@@ -44,6 +44,7 @@
 #include "svn_config.h"
 #include "svn_string.h"
 #include "svn_repos.h"
+#include "svn_pools.h"
 #include "svn_dirent_uri.h"
 #include "private/svn_fspath.h"
 
@@ -164,7 +165,8 @@ static const command_rec authz_svn_cmds[
  * Get the, possibly cached, svn_authz_t for this request.
  */
 static svn_authz_t *
-get_access_conf(request_rec *r, authz_svn_config_rec *conf)
+get_access_conf(request_rec *r, authz_svn_config_rec *conf,
+                apr_pool_t *scratch_pool)
 {
   const char *cache_key = NULL;
   const char *access_file;
@@ -182,7 +184,7 @@ get_access_conf(request_rec *r, authz_sv
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", dav_err->desc);
         return NULL;
       }
-      access_file = svn_dirent_join_many(r->pool, repos_path, "conf",
+      access_file = svn_dirent_join_many(scratch_pool, repos_path, "conf",
                                          conf->repo_relative_access_file,
                                          NULL);
     }
@@ -194,7 +196,7 @@ get_access_conf(request_rec *r, authz_sv
   ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                 "Path to authz file is %s", access_file);
 
-  cache_key = apr_pstrcat(r->pool, "mod_authz_svn:",
+  cache_key = apr_pstrcat(scratch_pool, "mod_authz_svn:",
                           access_file, (char *)NULL);
   apr_pool_userdata_get(&user_data, cache_key, r->connection->pool);
   access_conf = user_data;
@@ -243,12 +245,13 @@ convert_case(char *text, svn_boolean_t t
 /* Return the username to authorize, with case-conversion performed if
    CONF->force_username_case is set. */
 static char *
-get_username_to_authorize(request_rec *r, authz_svn_config_rec *conf)
+get_username_to_authorize(request_rec *r, authz_svn_config_rec *conf,
+                          apr_pool_t *pool)
 {
   char *username_to_authorize = r->user;
   if (username_to_authorize && conf->force_username_case)
     {
-      username_to_authorize = apr_pstrdup(r->pool, r->user);
+      username_to_authorize = apr_pstrdup(pool, r->user);
       convert_case(username_to_authorize,
                    strcasecmp(conf->force_username_case, "upper") == 0);
     }
@@ -283,7 +286,8 @@ req_check_access(request_rec *r,
   svn_authz_t *access_conf = NULL;
   svn_error_t *svn_err;
   char errbuf[256];
-  const char *username_to_authorize = get_username_to_authorize(r, conf);
+  const char *username_to_authorize = get_username_to_authorize(r, conf,
+                                                                r->pool);
 
   switch (r->method_number)
     {
@@ -419,7 +423,7 @@ req_check_access(request_rec *r,
     }
 
   /* Retrieve/cache authorization file */
-  access_conf = get_access_conf(r,conf);
+  access_conf = get_access_conf(r,conf, r->pool);
   if (access_conf == NULL)
     return DECLINED;
 
@@ -577,14 +581,13 @@ log_access_verdict(LOG_ARGS_SIGNATURE,
 }
 
 /*
- * This function is used as a provider to allow mod_dav_svn to bypass the
- * generation of an apache request when checking GET access from
- * "mod_dav_svn/authz.c" .
+ * Implementation of subreq_bypass with scratch_pool parameter.
  */
 static int
-subreq_bypass(request_rec *r,
-              const char *repos_path,
-              const char *repos_name)
+subreq_bypass2(request_rec *r,
+               const char *repos_path,
+               const char *repos_name,
+               apr_pool_t *scratch_pool)
 {
   svn_error_t *svn_err = NULL;
   svn_authz_t *access_conf = NULL;
@@ -595,7 +598,7 @@ subreq_bypass(request_rec *r,
 
   conf = ap_get_module_config(r->per_dir_config,
                               &authz_svn_module);
-  username_to_authorize = get_username_to_authorize(r, conf);
+  username_to_authorize = get_username_to_authorize(r, conf, scratch_pool);
 
   /* If configured properly, this should never be true, but just in case. */
   if (!conf->anonymous
@@ -606,7 +609,7 @@ subreq_bypass(request_rec *r,
     }
 
   /* Retrieve authorization file */
-  access_conf = get_access_conf(r, conf);
+  access_conf = get_access_conf(r, conf, scratch_pool);
   if (access_conf == NULL)
     return HTTP_FORBIDDEN;
 
@@ -620,7 +623,7 @@ subreq_bypass(request_rec *r,
                                              username_to_authorize,
                                              svn_authz_none|svn_authz_read,
                                              &authz_access_granted,
-                                             r->pool);
+                                             scratch_pool);
       if (svn_err)
         {
           ap_log_rerror(APLOG_MARK, APLOG_ERR,
@@ -650,6 +653,26 @@ subreq_bypass(request_rec *r,
 }
 
 /*
+ * This function is used as a provider to allow mod_dav_svn to bypass the
+ * generation of an apache request when checking GET access from
+ * "mod_dav_svn/authz.c" .
+ */
+static int
+subreq_bypass(request_rec *r,
+              const char *repos_path,
+              const char *repos_name)
+{
+  int status;
+  apr_pool_t *scratch_pool;
+
+  scratch_pool = svn_pool_create(r->pool);
+  status = subreq_bypass2(r, repos_path, repos_name, scratch_pool);
+  svn_pool_destroy(scratch_pool);
+
+  return status;
+}
+
+/*
  * Hooks
  */
 

Modified: subversion/branches/compressed-pristines/subversion/mod_dav_svn/activity.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_dav_svn/activity.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_dav_svn/activity.c (original)
+++ subversion/branches/compressed-pristines/subversion/mod_dav_svn/activity.c Sat Nov 24 20:29:11 2012
@@ -240,16 +240,21 @@ dav_svn__store_activity(const dav_svn_re
 dav_error *
 dav_svn__create_txn(const dav_svn_repos *repos,
                     const char **ptxn_name,
+                    apr_hash_t *revprops,
                     apr_pool_t *pool)
 {
   svn_revnum_t rev;
   svn_fs_txn_t *txn;
   svn_error_t *serr;
-  apr_hash_t *revprop_table = apr_hash_make(pool);
+
+  if (! revprops)
+    {
+      revprops = apr_hash_make(pool);
+    }
 
   if (repos->username)
     {
-      apr_hash_set(revprop_table, SVN_PROP_REVISION_AUTHOR, APR_HASH_KEY_STRING,
+      apr_hash_set(revprops, SVN_PROP_REVISION_AUTHOR, APR_HASH_KEY_STRING,
                    svn_string_create(repos->username, pool));
     }
 
@@ -262,8 +267,7 @@ dav_svn__create_txn(const dav_svn_repos 
     }
 
   serr = svn_repos_fs_begin_txn_for_commit2(&txn, repos->repos, rev,
-                                            revprop_table,
-                                            repos->pool);
+                                            revprops, repos->pool);
   if (serr != NULL)
     {
       return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,

Modified: subversion/branches/compressed-pristines/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_dav_svn/dav_svn.h?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/compressed-pristines/subversion/mod_dav_svn/dav_svn.h Sat Nov 24 20:29:11 2012
@@ -304,9 +304,6 @@ svn_boolean_t dav_svn__get_autoversionin
 /* for the repository referred to by this request, are bulk updates allowed? */
 svn_boolean_t dav_svn__get_bulk_updates_flag(request_rec *r);
 
-/* for the repository referred to by this request, should httpv2 be advertised? */
-svn_boolean_t dav_svn__get_v2_protocol_flag(request_rec *r);
-
 /* for the repository referred to by this request, are subrequests active? */
 svn_boolean_t dav_svn__get_pathauthz_flag(request_rec *r);
 
@@ -328,6 +325,17 @@ authz_svn__subreq_bypass_func_t dav_svn_
    SVNParentPath allowed? */
 svn_boolean_t dav_svn__get_list_parentpath_flag(request_rec *r);
 
+/* For the repository referred to by this request, should HTTPv2
+   protocol support be advertised?  Note that this also takes into
+   account the support level expected of based on the specified
+   master server version (if provided via SVNMasterVersion).  */
+svn_boolean_t dav_svn__check_httpv2_support(request_rec *r);
+
+/* For the repository referred to by this request, should ephemeral
+   txnprop support be advertised?  */
+svn_boolean_t dav_svn__check_ephemeral_txnprops_support(request_rec *r);
+
+
 
 /* SPECIAL URI
 
@@ -376,6 +384,11 @@ const char *dav_svn__get_xslt_uri(reques
 /* ### Is this assumed to be URI-encoded? */
 const char *dav_svn__get_master_uri(request_rec *r);
 
+/* Return the version of the master server (used for mirroring) iff a
+   master URI is in place for this location; otherwise, return NULL.
+   Comes from the <SVNMasterVersion> directive. */
+svn_version_t *dav_svn__get_master_version(request_rec *r);
+
 /* Return the disk path to the activities db.
    Comes from the <SVNActivitiesDB> directive. */
 const char *dav_svn__get_activities_db(request_rec *r);
@@ -386,10 +399,10 @@ const char *dav_svn__get_activities_db(r
 const char *dav_svn__get_root_dir(request_rec *r);
 
 /* Return the data compression level to be used over the wire. */
-int dav_svn__get_compression_level(void);
+int dav_svn__get_compression_level(request_rec *r);
 
 /* Return the hook script environment parsed from the configuration. */
-apr_hash_t *dav_svn__get_hooks_env(request_rec *r);
+const char *dav_svn__get_hooks_env(request_rec *r);
 
 /** For HTTP protocol v2, these are the new URIs and URI stubs
     returned to the client in our OPTIONS response.  They all depend
@@ -420,10 +433,17 @@ const char *dav_svn__get_vtxn_root_stub(
 /*** activity.c ***/
 
 /* Create a new transaction based on HEAD in REPOS, setting *PTXN_NAME
-   to the name of that transaction.  Use POOL for allocations. */
+   to the name of that transaction.  REVPROPS is an optional hash of
+   const char * property names and const svn_string_t * values which
+   will be set as transactions properties on the transaction this
+   function creates.  Use POOL for allocations.
+
+   NOTE:  This function will overwrite the svn:author property, if
+   any, found in REVPROPS.  */
 dav_error *
 dav_svn__create_txn(const dav_svn_repos *repos,
                     const char **ptxn_name,
+                    apr_hash_t *revprops,
                     apr_pool_t *pool);
 
 /* If it exists, abort the transaction named TXN_NAME from REPOS.  Use
@@ -620,6 +640,7 @@ static const dav_report_elem dav_svn__re
   { SVN_XML_NAMESPACE, "replay-report" },
   { SVN_XML_NAMESPACE, "get-deleted-rev-report" },
   { SVN_XML_NAMESPACE, SVN_DAV__MERGEINFO_REPORT },
+  { SVN_XML_NAMESPACE, SVN_DAV__INHERITED_PROPS_REPORT },
   { NULL, NULL },
 };
 
@@ -667,23 +688,22 @@ dav_svn__get_deleted_rev_report(const da
                                 const apr_xml_doc *doc,
                                 ap_filter_t *output);
 
+dav_error *
+dav_svn__get_inherited_props_report(const dav_resource *resource,
+                                    const apr_xml_doc *doc,
+                                    ap_filter_t *output);
 
 /*** posts/ ***/
 
-/* The list of Subversion's custom POSTs. */
-/* ### TODO:  Populate this list and transmit its contents in the
-   ### OPTIONS response.
-static const char * dav_svn__posts_list[] = {
-  "create-txn",
-  NULL
-};
-*/
-
 /* The various POST handlers, defined in posts/, and used by repos.c.  */
 dav_error *
 dav_svn__post_create_txn(const dav_resource *resource,
                          svn_skel_t *request_skel,
                          ap_filter_t *output);
+dav_error *
+dav_svn__post_create_txn_with_props(const dav_resource *resource,
+                                    svn_skel_t *request_skel,
+                                    ap_filter_t *output);
 
 /*** authz.c ***/
 
@@ -739,7 +759,11 @@ dav_svn__authz_read_func(dav_svn__authz_
    processing.  See dav_new_error_tag for parameter documentation.
    Note that DESC may be null (it's hard to track this down from
    dav_new_error_tag()'s documentation, but see the dav_error type,
-   which says that its desc field may be NULL). */
+   which says that its desc field may be NULL).
+
+   If ERROR_ID is 0, SVN_ERR_RA_DAV_REQUEST_FAILED will be used as a
+   default value for the error code.
+*/
 dav_error *
 dav_svn__new_error_tag(apr_pool_t *pool,
                        int status,
@@ -754,7 +778,11 @@ dav_svn__new_error_tag(apr_pool_t *pool,
    processing.  See dav_new_error for parameter documentation.
    Note that DESC may be null (it's hard to track this down from
    dav_new_error()'s documentation, but see the dav_error type,
-   which says that its desc field may be NULL). */
+   which says that its desc field may be NULL).
+
+   If ERROR_ID is 0, SVN_ERR_RA_DAV_REQUEST_FAILED will be used as a
+   default value for the error code.
+*/
 dav_error *
 dav_svn__new_error(apr_pool_t *pool,
                    int status,

Modified: subversion/branches/compressed-pristines/subversion/mod_dav_svn/deadprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_dav_svn/deadprops.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/branches/compressed-pristines/subversion/mod_dav_svn/deadprops.c Sat Nov 24 20:29:11 2012
@@ -1,5 +1,7 @@
 /*
- * deadprops.c: mod_dav_svn dead property provider functions for Subversion
+ * deadprops.c: mod_dav_svn provider functions for "dead properties"
+ *              (properties implemented by Subversion or its users,
+ *              not as part of the WebDAV specification).
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -512,10 +514,6 @@ db_store(dav_db *db,
   /* ### namespace check? */
   if (elem->first_child && !strcmp(elem->first_child->name, SVN_DAV__OLD_VALUE))
     {
-      const char *propname;
-
-      get_repos_propname(db, name, &propname);
-
       /* Parse OLD_PROPVAL. */
       old_propval = svn_string_create(dav_xml_get_cdata(elem->first_child, pool,
                                                         0 /* strip_white */),

Modified: subversion/branches/compressed-pristines/subversion/mod_dav_svn/liveprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_dav_svn/liveprops.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_dav_svn/liveprops.c (original)
+++ subversion/branches/compressed-pristines/subversion/mod_dav_svn/liveprops.c Sat Nov 24 20:29:11 2012
@@ -1,5 +1,7 @@
 /*
- * liveprops.c: mod_dav_svn live property provider functions for Subversion
+ * liveprops.c: mod_dav_svn provider functions for "live properties"
+ *              (properties implemented by the WebDAV specification
+ *              itself, not unique to Subversion or its users).
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -275,8 +277,8 @@ insert_prop_internal(const dav_resource 
                      int propid,
                      dav_prop_insert what,
                      apr_text_header *phdr,
-                     apr_pool_t *scratch_pool,
-                     apr_pool_t *result_pool)
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
 {
   const char *value = NULL;
   const char *s;
@@ -820,7 +822,7 @@ insert_prop(const dav_resource *resource
   scratch_pool = svn_pool_create(result_pool);
 
   rv = insert_prop_internal(resource, propid, what, phdr,
-                              scratch_pool, result_pool);
+                            result_pool, scratch_pool);
 
   svn_pool_destroy(scratch_pool);
   return rv;
@@ -958,7 +960,7 @@ dav_svn__insert_all_liveprops(request_re
     {
       svn_pool_clear(iterpool);
       (void) insert_prop_internal(resource, spec->propid, what, phdr,
-                                  iterpool, resource->pool);
+                                  resource->pool, iterpool);
     }
   svn_pool_destroy(iterpool);
 

Modified: subversion/branches/compressed-pristines/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_dav_svn/mod_dav_svn.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/compressed-pristines/subversion/mod_dav_svn/mod_dav_svn.c Sat Nov 24 20:29:11 2012
@@ -42,6 +42,7 @@
 #include "mod_dav_svn.h"
 
 #include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
 
 #include "dav_svn.h"
 #include "mod_authz_svn.h"
@@ -59,6 +60,12 @@
 typedef struct server_conf_t {
   const char *special_uri;
   svn_boolean_t use_utf8;
+
+  /* The compression level we will pass to svn_txdelta_to_svndiff3()
+   * for wire-compression. Negative value used to specify default
+     compression level. */
+  int compression_level;
+
 } server_conf_t;
 
 
@@ -92,11 +99,12 @@ typedef struct dir_conf_t {
   enum conf_flag list_parentpath;    /* whether to allow GET of parentpath */
   const char *root_dir;              /* our top-level directory */
   const char *master_uri;            /* URI to the master SVN repos */
+  svn_version_t *master_version;     /* version of master server */
   const char *activities_db;         /* path to activities database(s) */
   enum conf_flag txdelta_cache;      /* whether to enable txdelta caching */
   enum conf_flag fulltext_cache;     /* whether to enable fulltext caching */
   enum conf_flag revprop_cache;      /* whether to enable revprop caching */
-  apr_hash_t *hooks_env;             /* environment for hook scripts */
+  const char *hooks_env;             /* path to hook script env config file */
 } dir_conf_t;
 
 
@@ -109,10 +117,6 @@ extern module AP_MODULE_DECLARE_DATA dav
 /* The authz_svn provider for bypassing path authz. */
 static authz_svn__subreq_bypass_func_t pathauthz_bypass_func = NULL;
 
-/* The compression level we will pass to svn_txdelta_to_svndiff3()
- * for wire-compression */
-static int svn__compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
-
 static int
 init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
 {
@@ -163,7 +167,11 @@ init_dso(apr_pool_t *pconf, apr_pool_t *
 static void *
 create_server_config(apr_pool_t *p, server_rec *s)
 {
-  return apr_pcalloc(p, sizeof(server_conf_t));
+  server_conf_t *conf = apr_pcalloc(p, sizeof(server_conf_t));
+
+  conf->compression_level = -1;
+
+  return conf;
 }
 
 
@@ -179,6 +187,17 @@ merge_server_config(apr_pool_t *p, void 
 
   newconf->special_uri = INHERIT_VALUE(parent, child, special_uri);
 
+  if (child->compression_level < 0)
+    {
+      /* Inherit compression level from parent if not configured for this
+         VirtualHost. */
+      newconf->compression_level = parent->compression_level;
+    }
+  else
+    {
+      newconf->compression_level = child->compression_level;
+    }
+
   return newconf;
 }
 
@@ -214,6 +233,7 @@ merge_dir_config(apr_pool_t *p, void *ba
 
   newconf->fs_path = INHERIT_VALUE(parent, child, fs_path);
   newconf->master_uri = INHERIT_VALUE(parent, child, master_uri);
+  newconf->master_version = INHERIT_VALUE(parent, child, master_version);
   newconf->activities_db = INHERIT_VALUE(parent, child, activities_db);
   newconf->repo_name = INHERIT_VALUE(parent, child, repo_name);
   newconf->xslt_uri = INHERIT_VALUE(parent, child, xslt_uri);
@@ -282,6 +302,25 @@ SVNMasterURI_cmd(cmd_parms *cmd, void *c
 
 
 static const char *
+SVNMasterVersion_cmd(cmd_parms *cmd, void *config, const char *arg1)
+{
+  dir_conf_t *conf = config;
+  svn_error_t *err;
+  svn_version_t *version;
+
+  err = svn_version__parse_version_string(&version, arg1, cmd->pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return "Malformed master server version string.";
+    }
+  
+  conf->master_version = version;
+  return NULL;
+}
+
+
+static const char *
 SVNActivitiesDB_cmd(cmd_parms *cmd, void *config, const char *arg1)
 {
   dir_conf_t *conf = config;
@@ -513,6 +552,7 @@ SVNInMemoryCacheSize_cmd(cmd_parms *cmd,
 static const char *
 SVNCompressionLevel_cmd(cmd_parms *cmd, void *config, const char *arg1)
 {
+  server_conf_t *conf;
   int value = 0;
   svn_error_t *err = svn_cstring_atoi(&value, arg1);
   if (err)
@@ -530,7 +570,9 @@ SVNCompressionLevel_cmd(cmd_parms *cmd, 
                         (int)SVN_DELTA_COMPRESSION_LEVEL_NONE,
                         (int)SVN_DELTA_COMPRESSION_LEVEL_MAX);
 
-  svn__compression_level = value;
+  conf = ap_get_module_config(cmd->server->module_config,
+                              &dav_svn_module);
+  conf->compression_level = value;
 
   return NULL;
 }
@@ -550,43 +592,9 @@ SVNUseUTF8_cmd(cmd_parms *cmd, void *con
 static const char *
 SVNHooksEnv_cmd(cmd_parms *cmd, void *config, const char *arg1)
 {
-  apr_array_header_t *var;
-
-  var = svn_cstring_split(arg1, "=", TRUE, cmd->pool);
-  if (var && var->nelts >= 2)
-    {
-      dir_conf_t *conf = config;
-      const char *name;
-      const char *val;
-
-      if (! conf->hooks_env)
-        conf->hooks_env = apr_hash_make(cmd->pool);
-
-      name = apr_pstrdup(apr_hash_pool_get(conf->hooks_env),
-                         APR_ARRAY_IDX(var, 0, const char *));
-
-      /* Special case for values which contain '='. */
-      if (var->nelts > 2)
-        {
-          svn_stringbuf_t *buf;
-          int i;
-
-          buf = svn_stringbuf_create(APR_ARRAY_IDX(var, 1, const char *),
-                                     cmd->pool);
-          for (i = 2; i < var->nelts; i++)
-            {
-              svn_stringbuf_appendbyte(buf, '=');
-              svn_stringbuf_appendcstr(buf, APR_ARRAY_IDX(var, i, const char *));
-            }
+  dir_conf_t *conf = config;
 
-          val = apr_pstrdup(apr_hash_pool_get(conf->hooks_env), buf->data);
-        }
-      else
-        val = apr_pstrdup(apr_hash_pool_get(conf->hooks_env),
-                          APR_ARRAY_IDX(var, 1, const char *));
-
-      apr_hash_set(conf->hooks_env, name, APR_HASH_KEY_STRING, val);
-    }
+  conf->hooks_env = svn_dirent_internal_style(arg1, cmd->pool);
 
   return NULL;
 }
@@ -689,6 +697,16 @@ dav_svn__get_master_uri(request_rec *r)
 }
 
 
+svn_version_t *
+dav_svn__get_master_version(request_rec *r)
+{
+  dir_conf_t *conf;
+
+  conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
+  return conf->master_uri ? conf->master_version : NULL;
+}
+
+
 const char *
 dav_svn__get_xslt_uri(request_rec *r)
 {
@@ -786,12 +804,39 @@ dav_svn__get_bulk_updates_flag(request_r
 
 
 svn_boolean_t
-dav_svn__get_v2_protocol_flag(request_rec *r)
+dav_svn__check_httpv2_support(request_rec *r)
 {
   dir_conf_t *conf;
+  svn_boolean_t available;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->v2_protocol == CONF_FLAG_ON;
+  available = conf->v2_protocol == CONF_FLAG_ON;
+
+  /* If our configuration says that HTTPv2 is available, but we are
+     proxying requests to a master Subversion server which lacks
+     support for HTTPv2, we dumb ourselves down. */
+  if (available)
+    {
+      svn_version_t *version = dav_svn__get_master_version(r);
+      if (version && (! svn_version__at_least(version, 1, 7, 0)))
+        available = FALSE;
+    }
+  return available;
+}
+
+
+svn_boolean_t
+dav_svn__check_ephemeral_txnprops_support(request_rec *r)
+{
+  svn_version_t *version = dav_svn__get_master_version(r);
+
+  /* We know this server supports ephemeral txnprops.  But if we're
+     proxying requests to a master server, we need to see if it
+     supports them, too.  */
+  if (version && (! svn_version__at_least(version, 1, 8, 0)))
+    return FALSE;
+
+  return TRUE;
 }
 
 
@@ -873,12 +918,24 @@ dav_svn__get_revprop_cache_flag(request_
 
 
 int
-dav_svn__get_compression_level(void)
+dav_svn__get_compression_level(request_rec *r)
 {
-  return svn__compression_level;
+  server_conf_t *conf;
+
+  conf = ap_get_module_config(r->server->module_config,
+                              &dav_svn_module);
+
+  if (conf->compression_level < 0)
+    {
+      return SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
+    }
+  else
+    {
+      return conf->compression_level;
+    }
 }
 
-apr_hash_t *
+const char *
 dav_svn__get_hooks_env(request_rec *r)
 {
   dir_conf_t *conf;
@@ -1077,6 +1134,11 @@ static const command_rec cmds[] =
                 "specifies a URI to access a master Subversion repository"),
 
   /* per directory/location */
+  AP_INIT_TAKE1("SVNMasterVersion", SVNMasterVersion_cmd, NULL, ACCESS_CONF,
+                "specifies the Subversion release version of a master "
+                "Subversion server "),
+  
+  /* per directory/location */
   AP_INIT_TAKE1("SVNActivitiesDB", SVNActivitiesDB_cmd, NULL, ACCESS_CONF,
                 "specifies the location in the filesystem in which the "
                 "activities database(s) should be stored"),
@@ -1136,10 +1198,12 @@ static const command_rec cmds[] =
                "use UTF-8 as native character encoding (default is ASCII)."),
 
   /* per directory/location */
-  AP_INIT_ITERATE("SVNHooksEnv", SVNHooksEnv_cmd, NULL,
-                  ACCESS_CONF|RSRC_CONF,
-                  "Set the environment of hook scripts via any number of "
-                  "VAR=VAL arguments (the default hook environment is empty)."),
+  AP_INIT_TAKE1("SVNHooksEnv", SVNHooksEnv_cmd, NULL,
+                ACCESS_CONF|RSRC_CONF,
+                "Sets the path to the configuration file for the environment "
+                "of hook scripts. If not absolute, the path is relative to "
+                "the repository's conf directory (by default the hooks-env "
+                "file in the repository is used)."),
   { NULL }
 };
 

Modified: subversion/branches/compressed-pristines/subversion/mod_dav_svn/posts/create_txn.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/mod_dav_svn/posts/create_txn.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/mod_dav_svn/posts/create_txn.c (original)
+++ subversion/branches/compressed-pristines/subversion/mod_dav_svn/posts/create_txn.c Sat Nov 24 20:29:11 2012
@@ -42,13 +42,64 @@ dav_svn__post_create_txn(const dav_resou
   request_rec *r = resource->info->r;
 
   /* Create a Subversion repository transaction based on HEAD. */
-  if ((derr = dav_svn__create_txn(resource->info->repos, &txn_name,
+  if ((derr = dav_svn__create_txn(resource->info->repos, &txn_name, NULL,
                                   resource->pool)))
     return derr;
 
   /* Build a "201 Created" response with header that tells the
      client our new transaction's name. */
-  vtxn_name =  apr_table_get(r->headers_in, SVN_DAV_VTXN_NAME_HEADER);
+  vtxn_name = apr_table_get(r->headers_in, SVN_DAV_VTXN_NAME_HEADER);
+  if (vtxn_name && vtxn_name[0])
+    {
+      /* If the client supplied a vtxn name then store a mapping from
+         the client name to the FS transaction name in the activity
+         database. */
+      if ((derr  = dav_svn__store_activity(resource->info->repos,
+                                           vtxn_name, txn_name)))
+        return derr;
+      apr_table_set(r->headers_out, SVN_DAV_VTXN_NAME_HEADER, vtxn_name);
+    }
+  else
+    apr_table_set(r->headers_out, SVN_DAV_TXN_NAME_HEADER, txn_name);
+
+  r->status = HTTP_CREATED;
+
+  return NULL;
+}
+
+
+/* Respond to a "create-txn-with-props" POST request.
+ *
+ * Syntax:  ( create-txn-with-props (PROPNAME PROPVAL [PROPNAME PROPVAL ...])
+ */
+dav_error *
+dav_svn__post_create_txn_with_props(const dav_resource *resource,
+                                    svn_skel_t *request_skel,
+                                    ap_filter_t *output)
+{
+  const char *txn_name;
+  const char *vtxn_name;
+  dav_error *derr;
+  svn_error_t *err;
+  request_rec *r = resource->info->r;
+  apr_hash_t *revprops;
+  svn_skel_t *proplist_skel = request_skel->children->next;
+
+  if ((err = svn_skel__parse_proplist(&revprops, proplist_skel,
+                                      resource->pool)))
+    {
+      return dav_svn__convert_err(err, HTTP_BAD_REQUEST,
+                                  "Malformatted request skel", resource->pool);
+    }
+  
+  /* Create a Subversion repository transaction based on HEAD. */
+  if ((derr = dav_svn__create_txn(resource->info->repos, &txn_name,
+                                  revprops, resource->pool)))
+    return derr;
+
+  /* Build a "201 Created" response with header that tells the
+     client our new transaction's name. */
+  vtxn_name = apr_table_get(r->headers_in, SVN_DAV_VTXN_NAME_HEADER);
   if (vtxn_name && vtxn_name[0])
     {
       /* If the client supplied a vtxn name then store a mapping from