subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1515362 [4/13] - in /subversion/branches/move-tracking-1: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ notes/tree-conflicts/ subversion/bindings/cxxhl/include/ subversion/bindings/cxxhl/include/svncxxhl/ subversio...
Date Mon, 19 Aug 2013 11:21:06 GMT
Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/cleanup.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/cleanup.c Mon Aug 19 11:21:01 2013
@@ -32,32 +32,210 @@
 #include "svn_client.h"
 #include "svn_config.h"
 #include "svn_dirent_uri.h"
+#include "svn_hash.h"
 #include "svn_path.h"
 #include "svn_pools.h"
 #include "client.h"
 #include "svn_props.h"
 
 #include "svn_private_config.h"
+#include "private/svn_wc_private.h"
 
 
 /*** Code. ***/
 
+struct cleanup_status_walk_baton
+{
+  svn_boolean_t include_externals;
+  svn_boolean_t remove_unversioned_items;
+  svn_boolean_t remove_ignored_items;
+  svn_client_ctx_t *ctx;
+};
+
+/* Forward declararion. */
+static svn_error_t *
+cleanup_status_walk(void *baton,
+                    const char *local_abspath,
+                    const svn_wc_status3_t *status,
+                    apr_pool_t *scratch_pool);
+
+static svn_error_t *
+do_cleanup(const char *local_abspath,
+           svn_boolean_t include_externals,
+           svn_boolean_t remove_unversioned_items,
+           svn_boolean_t remove_ignored_items,
+           svn_client_ctx_t *ctx,
+           apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+
+  if (remove_unversioned_items || remove_ignored_items)
+    {
+      svn_boolean_t is_locked_here;
+      svn_boolean_t is_locked;
+      svn_boolean_t sqlite_exclusive;
+      svn_config_t *cfg = ctx->config
+                          ? svn_hash_gets(ctx->config,
+                                          SVN_CONFIG_CATEGORY_CONFIG)
+                          : NULL;
+
+      /* Check if someone else owns a lock for LOCAL_ABSPATH. */
+      SVN_ERR(svn_wc_locked2(&is_locked_here, &is_locked, ctx->wc_ctx,
+                             local_abspath, scratch_pool));
+      if (is_locked && !is_locked_here)
+        return svn_error_createf(SVN_ERR_WC_LOCKED, NULL,
+                                 _("Working copy at '%s' is already locked."),
+                                 svn_dirent_local_style(local_abspath,
+                                                        scratch_pool));
+
+      SVN_ERR(svn_config_get_bool(cfg, &sqlite_exclusive,
+                                  SVN_CONFIG_SECTION_WORKING_COPY,
+                                  SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE,
+                                  FALSE));
+      if (sqlite_exclusive)
+        {
+          /* Close the db because svn_wc_cleanup3() will try to open it again,
+           * which doesn't work if exclusive sqlite locking mode is enabled. */
+          SVN_ERR(svn_wc__close_db(local_abspath, ctx->wc_ctx, scratch_pool));
+        }
+    }
+
+  err = svn_wc_cleanup3(ctx->wc_ctx, local_abspath, ctx->cancel_func,
+                        ctx->cancel_baton, scratch_pool);
+  svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
+  if (err)
+    return svn_error_trace(err);
+
+  if (remove_unversioned_items || remove_ignored_items || include_externals)
+    {
+      struct cleanup_status_walk_baton b;
+      apr_array_header_t *ignores;
+
+      b.include_externals = include_externals;
+      b.remove_unversioned_items = remove_unversioned_items;
+      b.remove_ignored_items = remove_ignored_items;
+      b.include_externals = include_externals;
+      b.ctx = ctx;
+
+      SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, scratch_pool));
+      SVN_ERR(svn_wc_walk_status(ctx->wc_ctx, local_abspath,
+                                 svn_depth_infinity,
+                                 TRUE,  /* get all */
+                                 remove_ignored_items,
+                                 TRUE,  /* ignore textmods */
+                                 ignores,
+                                 cleanup_status_walk, &b,
+                                 ctx->cancel_func,
+                                 ctx->cancel_baton,
+                                 scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* An implementation of svn_wc_status_func4_t. */
+static svn_error_t *
+cleanup_status_walk(void *baton,
+                    const char *local_abspath,
+                    const svn_wc_status3_t *status,
+                    apr_pool_t *scratch_pool)
+{
+  struct cleanup_status_walk_baton *b = baton;
+  svn_node_kind_t kind_on_disk;
+  svn_wc_notify_t *notify;
+
+  if (status->node_status == svn_wc_status_external && b->include_externals)
+    {
+      svn_error_t *err;
+
+      SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+      if (kind_on_disk == svn_node_dir)
+        {
+          if (b->ctx->notify_func2)
+            {
+              notify = svn_wc_create_notify(local_abspath,
+                                            svn_wc_notify_cleanup_external,
+                                            scratch_pool);
+              (*b->ctx->notify_func2)(b->ctx->notify_baton2, notify,
+                                      scratch_pool);
+            }
+
+          err = do_cleanup(local_abspath, b->include_externals,
+                            b->remove_unversioned_items,
+                            b->remove_ignored_items,
+                            b->ctx, scratch_pool);
+          if (err && err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY)
+            {
+              svn_error_clear(err);
+              return SVN_NO_ERROR;
+            }
+          else
+            SVN_ERR(err);
+        }
+
+      return SVN_NO_ERROR;
+    }
+
+  if (status->node_status == svn_wc_status_ignored)
+    {
+      if (!b->remove_ignored_items)
+        return SVN_NO_ERROR;
+    }
+  else if (status->node_status == svn_wc_status_unversioned)
+    {
+      if (!b->remove_unversioned_items)
+        return SVN_NO_ERROR;
+    }
+  else
+    return SVN_NO_ERROR;
+
+  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+  switch (kind_on_disk)
+    {
+      case svn_node_file:
+      case svn_node_symlink:
+        SVN_ERR(svn_io_remove_file2(local_abspath, FALSE, scratch_pool));
+        break;
+      case svn_node_dir:
+        SVN_ERR(svn_io_remove_dir2(local_abspath, FALSE,
+                                   b->ctx->cancel_func, b->ctx->cancel_baton,
+                                   scratch_pool));
+        break;
+      case svn_node_none:
+      default:
+        return SVN_NO_ERROR;
+    }
+
+  if (b->ctx->notify_func2)
+    {
+      notify = svn_wc_create_notify(local_abspath, svn_wc_notify_delete,
+                                    scratch_pool);
+      notify->kind = kind_on_disk;
+      (*b->ctx->notify_func2)(b->ctx->notify_baton2, notify, scratch_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
-svn_client_cleanup(const char *path,
-                   svn_client_ctx_t *ctx,
-                   apr_pool_t *scratch_pool)
+svn_client_cleanup2(const char *path,
+                    svn_boolean_t include_externals,
+                    svn_boolean_t remove_unversioned_items,
+                    svn_boolean_t remove_ignored_items,
+                    svn_client_ctx_t *ctx,
+                    apr_pool_t *scratch_pool)
 {
   const char *local_abspath;
-  svn_error_t *err;
 
   if (svn_path_is_url(path))
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                              _("'%s' is not a local path"), path);
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
+  SVN_ERR(do_cleanup(local_abspath, include_externals,
+                     remove_unversioned_items, remove_ignored_items,
+                     ctx, scratch_pool));
 
-  err = svn_wc_cleanup3(ctx->wc_ctx, local_abspath, ctx->cancel_func,
-                        ctx->cancel_baton, scratch_pool);
-  svn_io_sleep_for_timestamps(path, scratch_pool);
-  return svn_error_trace(err);
+  return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/client.h?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/client.h (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/client.h Mon Aug 19 11:21:01 2013
@@ -20,7 +20,8 @@
  *    under the License.
  * ====================================================================
  */
-
+
+
 
 #ifndef SVN_LIBSVN_CLIENT_H
 #define SVN_LIBSVN_CLIENT_H
@@ -208,7 +209,9 @@ svn_client__repos_location_segments(apr_
    Use the authentication baton cached in CTX to authenticate against
    the repository.  Use POOL for all allocations.
 
-   See also svn_client__youngest_common_ancestor().
+   See also svn_client__calc_youngest_common_ancestor() to find youngest
+   common ancestor for already fetched history-as-mergeinfo information.
+
 */
 svn_error_t *
 svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
@@ -219,6 +222,34 @@ svn_client__get_youngest_common_ancestor
                                          apr_pool_t *result_pool,
                                          apr_pool_t *scratch_pool);
 
+/* Find the common ancestor of two locations in a repository using already
+   fetched history-as-mergeinfo information.
+
+   Ancestry is determined by the 'copy-from' relationship and the normal
+   successor relationship.
+
+   Set *ANCESTOR_P to the location of the youngest common ancestor of
+   LOC1 and LOC2.  If the locations have no common ancestor (including if
+   they don't have the same repository root URL), set *ANCESTOR_P to NULL.
+
+   HISTORY1, HAS_REV_ZERO_HISTORY1, HISTORY2, HAS_REV_ZERO_HISTORY2 are
+   history-as-mergeinfo information as returned by
+   svn_client__get_history_as_mergeinfo() for LOC1 and LOC2 respectively.
+
+   See also svn_client__get_youngest_common_ancestor().
+
+*/
+svn_error_t *
+svn_client__calc_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+                                          const svn_client__pathrev_t *loc1,
+                                          apr_hash_t *history1,
+                                          svn_boolean_t has_rev_zero_history1,
+                                          const svn_client__pathrev_t *loc2,
+                                          apr_hash_t *history2,
+                                          svn_boolean_t has_rev_zero_history2,
+                                          apr_pool_t *result_pool,
+                                          apr_pool_t *scratch_pool);
+
 /* Ensure that RA_SESSION's session URL matches SESSION_URL,
    reparenting that session if necessary.
    Store the previous session URL in *OLD_SESSION_URL (so that if the
@@ -247,7 +278,8 @@ svn_client__ensure_ra_session_url(const 
                                   apr_pool_t *pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** RA callbacks ***/
 
 
@@ -329,7 +361,8 @@ svn_client__ra_make_cb_baton(svn_wc_cont
                              apr_pool_t *result_pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Add/delete ***/
 
 /* If AUTOPROPS is not null: Then read automatic properties matching PATH
@@ -442,7 +475,8 @@ svn_client__make_local_parents(const cha
                                apr_pool_t *pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Checkout, update and switch ***/
 
 /* Update a working copy LOCAL_ABSPATH to REVISION, and (if not NULL) set
@@ -581,7 +615,8 @@ svn_client__switch_internal(svn_revnum_t
                             apr_pool_t *pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Inheritable Properties ***/
 
 /* Convert any svn_prop_inherited_item_t elements in INHERITED_PROPS which
@@ -626,7 +661,8 @@ svn_client__get_inheritable_props(apr_ha
                                   apr_pool_t *scratch_pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Editor for repository diff ***/
 
 /* Create an editor for a pure repository comparison, i.e. comparing one
@@ -666,7 +702,8 @@ svn_client__get_diff_editor2(const svn_d
                              apr_pool_t *result_pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Editor for diff summary ***/
 
 /* Set *CALLBACKS and *CALLBACK_BATON to a set of diff callbacks that will
@@ -689,7 +726,8 @@ svn_client__get_diff_summarize_callbacks
                         apr_pool_t *pool);
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Copy Stuff ***/
 
 /* This structure is used to associate a specific copy or move SRC with a
@@ -730,7 +768,8 @@ typedef struct svn_client__copy_pair_t
 } svn_client__copy_pair_t;
 
 /* ---------------------------------------------------------------- */
-
+
+
 /*** Commit Stuff ***/
 
 /* WARNING: This is all new, untested, un-peer-reviewed conceptual
@@ -944,7 +983,8 @@ svn_client__do_commit(const char *base_u
                       apr_pool_t *scratch_pool);
 
 
-
+
+
 /*** Externals (Modules) ***/
 
 /* Handle changes to the svn:externals property described by EXTERNALS_NEW,
@@ -1116,7 +1156,8 @@ svn_client__resolve_conflicts(svn_boolea
                               svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool);
 
-
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/commit.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/commit.c Mon Aug 19 11:21:01 2013
@@ -240,6 +240,13 @@ post_process_commit_item(svn_wc_committe
   remove_lock = (! keep_locks && (item->state_flags
                                        & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN));
 
+  /* When the node was deleted (or replaced), we need to always remove the 
+     locks, as they're invalidated on the server. We cannot honor the 
+     SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN flag here because it does not tell
+     us whether we have locked children. */
+  if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+    remove_lock = TRUE;
+
   return svn_wc_queue_committed3(queue, wc_ctx, item->path,
                                  loop_recurse, item->incoming_prop_changes,
                                  remove_lock, !keep_changelists,

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/copy.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/copy.c Mon Aug 19 11:21:01 2013
@@ -385,6 +385,7 @@ static svn_error_t *
 verify_wc_dsts(const apr_array_header_t *copy_pairs,
                svn_boolean_t make_parents,
                svn_boolean_t is_move,
+               svn_boolean_t metadata_only,
                svn_client_ctx_t *ctx,
                apr_pool_t *result_pool,
                apr_pool_t *scratch_pool)
@@ -435,8 +436,11 @@ verify_wc_dsts(const apr_array_header_t 
         }
 
       /* Check that there is no unversioned obstruction */
-      SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind,
-                                iterpool));
+      if (metadata_only)
+        dst_kind = svn_node_none;
+      else
+        SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind,
+                                  iterpool));
 
       if (dst_kind != svn_node_none)
         {
@@ -527,6 +531,7 @@ static svn_error_t *
 verify_wc_srcs_and_dsts(const apr_array_header_t *copy_pairs,
                         svn_boolean_t make_parents,
                         svn_boolean_t is_move,
+                        svn_boolean_t metadata_only,
                         svn_client_ctx_t *ctx,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool)
@@ -557,7 +562,7 @@ verify_wc_srcs_and_dsts(const apr_array_
                                         scratch_pool));
     }
 
-  SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, ctx,
+  SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, metadata_only, ctx,
                          result_pool, iterpool));
 
   svn_pool_destroy(iterpool);
@@ -1419,7 +1424,7 @@ wc_to_repos_copy(const apr_array_header_
 #ifdef ENABLE_EV2_SHIMS
   if (commit_items)
     {
-      relpath_map = apr_hash_make(pool);
+      relpath_map = apr_hash_make(scratch_pool);
       for (i = 0; i < commit_items->nelts; i++)
         {
           svn_client_commit_item3_t *item = APR_ARRAY_IDX(commit_items, i,
@@ -1692,8 +1697,8 @@ repos_to_wc_copy_locked(svn_boolean_t *t
   /* We've already checked for physical obstruction by a working file.
      But there could also be logical obstruction by an entry whose
      working file happens to be missing.*/
-  SVN_ERR(verify_wc_dsts(copy_pairs, FALSE, FALSE, ctx,
-                         scratch_pool, iterpool));
+  SVN_ERR(verify_wc_dsts(copy_pairs, FALSE, FALSE, FALSE /* metadata_only */,
+                         ctx, scratch_pool, iterpool));
 
   /* Decide whether the two repositories are the same or not. */
   {
@@ -2175,7 +2180,7 @@ try_copy(svn_boolean_t *timestamp_sleep,
   if ((! srcs_are_urls) && (! dst_is_url))
     {
       SVN_ERR(verify_wc_srcs_and_dsts(copy_pairs, make_parents, is_move,
-                                      ctx, pool, pool));
+                                      metadata_only, ctx, pool, pool));
 
       /* Copy or move all targets. */
       if (is_move)

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/deprecated.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/deprecated.c Mon Aug 19 11:21:01 2013
@@ -2964,3 +2964,11 @@ svn_client_commit_item2_dup(const svn_cl
   return new_item;
 }
 
+svn_error_t *
+svn_client_cleanup(const char *path,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(svn_client_cleanup2(path, FALSE, FALSE, FALSE, ctx,
+                                             scratch_pool));
+}

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/diff.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/diff.c Mon Aug 19 11:21:01 2013
@@ -51,6 +51,7 @@
 #include "private/svn_wc_private.h"
 #include "private/svn_diff_private.h"
 #include "private/svn_subr_private.h"
+#include "private/svn_io_private.h"
 
 #include "svn_private_config.h"
 
@@ -807,14 +808,23 @@ diff_content_changed(svn_boolean_t *wrot
        * ### a non-git compatible diff application.*/
 
       /* We deal in streams, but svn_io_run_diff2() deals in file handles,
-         unfortunately, so we need to make these temporary files, and then
-         copy the contents to our stream. */
-      SVN_ERR(svn_io_open_unique_file3(&outfile, &outfilename, NULL,
-                                       svn_io_file_del_on_pool_cleanup,
-                                       scratch_pool, scratch_pool));
-      SVN_ERR(svn_io_open_unique_file3(&errfile, &errfilename, NULL,
-                                       svn_io_file_del_on_pool_cleanup,
-                                       scratch_pool, scratch_pool));
+         so we may need to make temporary files and then copy the contents
+         to our stream. */
+      outfile = svn_stream__aprfile(outstream);
+      if (outfile)
+        outfilename = NULL;
+      else
+        SVN_ERR(svn_io_open_unique_file3(&outfile, &outfilename, NULL,
+                                         svn_io_file_del_on_pool_cleanup,
+                                         scratch_pool, scratch_pool));
+
+      errfile = svn_stream__aprfile(errstream);
+      if (errfile)
+        errfilename = NULL;
+      else
+        SVN_ERR(svn_io_open_unique_file3(&errfile, &errfilename, NULL,
+                                         svn_io_file_del_on_pool_cleanup,
+                                         scratch_pool, scratch_pool));
 
       SVN_ERR(svn_io_run_diff2(".",
                                diff_cmd_baton->options.for_external.argv,
@@ -824,20 +834,25 @@ diff_content_changed(svn_boolean_t *wrot
                                &exitcode, outfile, errfile,
                                diff_cmd_baton->diff_cmd, scratch_pool));
 
-      SVN_ERR(svn_io_file_close(outfile, scratch_pool));
-      SVN_ERR(svn_io_file_close(errfile, scratch_pool));
-
       /* Now, open and copy our files to our output streams. */
-      SVN_ERR(svn_stream_open_readonly(&stream, outfilename,
-                                       scratch_pool, scratch_pool));
-      SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(outstream,
-                               scratch_pool),
-                               NULL, NULL, scratch_pool));
-      SVN_ERR(svn_stream_open_readonly(&stream, errfilename,
-                                       scratch_pool, scratch_pool));
-      SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(errstream,
-                                                         scratch_pool),
-                               NULL, NULL, scratch_pool));
+      if (outfilename)
+        {
+          SVN_ERR(svn_io_file_close(outfile, scratch_pool));
+          SVN_ERR(svn_stream_open_readonly(&stream, outfilename,
+                                           scratch_pool, scratch_pool));
+          SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(outstream,
+                                                             scratch_pool),
+                                   NULL, NULL, scratch_pool));
+        }
+      if (errfilename)
+        {
+          SVN_ERR(svn_io_file_close(errfile, scratch_pool));
+          SVN_ERR(svn_stream_open_readonly(&stream, errfilename,
+                                           scratch_pool, scratch_pool));
+          SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(errstream,
+                                                             scratch_pool),
+                                   NULL, NULL, scratch_pool));
+        }
 
       /* We have a printed a diff for this path, mark it as visited. */
       *wrote_header = TRUE;

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/log.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/log.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/log.c Mon Aug 19 11:21:01 2013
@@ -712,7 +712,17 @@ run_ra_get_log(apr_array_header_t *revis
       matching_segment = bsearch(&younger_rev, log_segments->elts,
                                  log_segments->nelts, log_segments->elt_size,
                                  compare_rev_to_segment);
-      SVN_ERR_ASSERT(*matching_segment);
+      /* LOG_SEGMENTS is supposed to represent the history of PATHS from
+         the oldest to youngest revs in REVISION_RANGES.  This function's
+         current sole caller svn_client_log5 *should* be providing
+         LOG_SEGMENTS that span the oldest to youngest revs in
+         REVISION_RANGES, even if one or more of the svn_location_segment_t's
+         returned have NULL path members indicating a gap in the history. So
+         MATCHING_SEGMENT should never be NULL, but clearly sometimes it is,
+         see http://svn.haxx.se/dev/archive-2013-06/0522.shtml
+         So to be safe we handle that case. */
+      if (matching_segment == NULL)
+        continue;
       
       /* A segment with a NULL path means there is gap in the history.
          We'll just proceed and let svn_ra_get_log2 fail with a useful
@@ -827,7 +837,7 @@ svn_client_log5(const apr_array_header_t
   SVN_ERR(resolve_log_targets(&relative_targets, &ra_target, &peg_rev,
                               targets, ctx, pool, pool));
 
-  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, NULL,
                                             ra_target, NULL, &peg_rev, &peg_rev,
                                             ctx, pool));
 
@@ -850,13 +860,32 @@ svn_client_log5(const apr_array_header_t
   SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
                                             actual_loc->url, pool));
 
-  /* Get the svn_location_segment_t's representing the requested log ranges. */
-  SVN_ERR(svn_client__repos_location_segments(&log_segments, ra_session,
-                                              actual_loc->url,
-                                              actual_loc->rev, /* peg */
-                                              actual_loc->rev, /* start */
-                                              oldest_rev,      /* end */
-                                              ctx, pool));
+  /* Save us an RA layer round trip if we are on the repository root and
+     know the result in advance.  All the revision data has already been
+     validated.
+   */
+  if (strcmp(actual_loc->url, actual_loc->repos_root_url) == 0)
+    {
+      svn_location_segment_t *segment = apr_pcalloc(pool, sizeof(*segment));
+      log_segments = apr_array_make(pool, 1, sizeof(segment));
+
+      segment->range_start = oldest_rev;
+      segment->range_end = actual_loc->rev;
+      segment->path = "";
+      APR_ARRAY_PUSH(log_segments, svn_location_segment_t *) = segment;
+    }
+  else
+    {
+      /* Get the svn_location_segment_t's representing the requested log
+       * ranges. */
+      SVN_ERR(svn_client__repos_location_segments(&log_segments, ra_session,
+                                                  actual_loc->url,
+                                                  actual_loc->rev, /* peg */
+                                                  actual_loc->rev, /* start */
+                                                  oldest_rev,      /* end */
+                                                  ctx, pool));
+    }
+
 
   SVN_ERR(run_ra_get_log(revision_ranges, relative_targets, log_segments,
                          actual_loc, ra_session, targets, limit,

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/merge.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/merge.c Mon Aug 19 11:21:01 2013
@@ -1198,7 +1198,7 @@ struct merge_dir_baton_t
   apr_hash_t *pending_deletes;
 
   /* NULL, or an hashtable mapping const char * LOCAL_ABSPATHs to
-     a const svn_wc_conflict_description2_t * instance, describing the just
+     a const svn_wc_conflict_description3_t * instance, describing the just
      installed conflict */
   apr_hash_t *new_tree_conflicts;
 
@@ -1301,12 +1301,15 @@ record_tree_conflict(merge_cmd_baton_t *
                      svn_node_kind_t node_kind,
                      svn_wc_conflict_action_t action,
                      svn_wc_conflict_reason_t reason,
-                     const svn_wc_conflict_description2_t *existing_conflict,
+                     const svn_wc_conflict_description3_t *existing_conflict,
                      svn_boolean_t notify_tc,
                      apr_pool_t *scratch_pool)
 {
   svn_wc_context_t *wc_ctx = merge_b->ctx->wc_ctx;
 
+  if (merge_b->record_only)
+    return SVN_NO_ERROR;
+
   if (merge_b->merge_source.ancestral
       || merge_b->reintegrate_merge)
     {
@@ -1316,10 +1319,9 @@ record_tree_conflict(merge_cmd_baton_t *
   alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
                        merge_b->pool);
 
-
-  if (!merge_b->record_only && !merge_b->dry_run)
+  if (!merge_b->dry_run)
     {
-       svn_wc_conflict_description2_t *conflict;
+       svn_wc_conflict_description3_t *conflict;
        const svn_wc_conflict_version_t *left;
        const svn_wc_conflict_version_t *right;
        apr_pool_t *result_pool = parent_baton ? parent_baton->pool
@@ -1358,7 +1360,7 @@ record_tree_conflict(merge_cmd_baton_t *
       if (existing_conflict != NULL && existing_conflict->src_left_version)
           left = existing_conflict->src_left_version;
 
-      conflict = svn_wc_conflict_description_create_tree2(
+      conflict = svn_wc_conflict_description_create_tree3(
                         local_abspath, node_kind, svn_wc_operation_merge,
                         left, right, result_pool);
 
@@ -1848,7 +1850,7 @@ merge_file_opened(void **new_file_baton,
     }
   else
     {
-      const svn_wc_conflict_description2_t *old_tc = NULL;
+      const svn_wc_conflict_description3_t *old_tc = NULL;
 
       /* The node doesn't exist pre-merge: We have an addition */
       fb->added = TRUE;
@@ -2605,7 +2607,7 @@ merge_dir_opened(void **new_dir_baton,
     }
   else
     {
-      const svn_wc_conflict_description2_t *old_tc = NULL;
+      const svn_wc_conflict_description3_t *old_tc = NULL;
 
       /* The node doesn't exist pre-merge: We have an addition */
       db->added = TRUE;
@@ -12031,7 +12033,7 @@ operative_rev_receiver(void *baton,
 /* Wrapper around svn_client__mergeinfo_log. All arguments are as per
    that private API.  The discover_changed_paths, depth, and revprops args to
    svn_client__mergeinfo_log are always TRUE, svn_depth_infinity_t,
-   and NULL respectively.
+   and empty array respectively.
 
    If RECEIVER raises a SVN_ERR_CEASE_INVOCATION error, but still sets
    *REVISION to a valid revnum, then clear the error.  Otherwise return
@@ -12051,18 +12053,22 @@ short_circuit_mergeinfo_log(svn_mergeinf
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
 {
-  svn_error_t *err = svn_client__mergeinfo_log(finding_merged,
-                                               target_path_or_url,
-                                               target_peg_revision,
-                                               target_mergeinfo_cat,
-                                               source_path_or_url,
-                                               source_peg_revision,
-                                               source_start_revision,
-                                               source_end_revision,
-                                               receiver, revision,
-                                               TRUE, svn_depth_infinity,
-                                               NULL, ctx, result_pool,
-                                               scratch_pool);
+  apr_array_header_t *revprops;
+  svn_error_t *err;
+
+  revprops = apr_array_make(scratch_pool, 0, sizeof(const char *));
+  err = svn_client__mergeinfo_log(finding_merged,
+                                  target_path_or_url,
+                                  target_peg_revision,
+                                  target_mergeinfo_cat,
+                                  source_path_or_url,
+                                  source_peg_revision,
+                                  source_start_revision,
+                                  source_end_revision,
+                                  receiver, revision,
+                                  TRUE, svn_depth_infinity,
+                                  revprops, ctx, result_pool,
+                                  scratch_pool);
 
   if (err)
     {
@@ -12304,9 +12310,13 @@ find_automatic_merge(svn_client__pathrev
             &s_t->target->loc, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
             s_t->target_ra_session, ctx, scratch_pool));
 
-  SVN_ERR(svn_client__get_youngest_common_ancestor(
-            &s_t->yca, s_t->source, &s_t->target->loc, s_t->source_ra_session,
-            ctx, result_pool, result_pool));
+  SVN_ERR(svn_client__calc_youngest_common_ancestor(
+            &s_t->yca, s_t->source, s_t->source_branch.history,
+            s_t->source_branch.has_r0_history,
+            &s_t->target->loc, s_t->target_branch.history,
+            s_t->target_branch.has_r0_history,
+            result_pool, scratch_pool));
+
   if (! s_t->yca)
     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
                              _("'%s@%ld' must be ancestrally related to "

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/patch.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/patch.c Mon Aug 19 11:21:01 2013
@@ -2815,10 +2815,13 @@ check_ancestor_delete(const char *delete
 {
   struct can_delete_baton_t cb;
   svn_error_t *err;
+  apr_array_header_t *ignores;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   const char *dir_abspath = svn_dirent_dirname(deleted_target, scratch_pool);
 
+  SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, scratch_pool));
+
   while (svn_dirent_is_child(apply_root, dir_abspath, iterpool))
     {
       svn_pool_clear(iterpool);
@@ -2828,7 +2831,7 @@ check_ancestor_delete(const char *delete
       cb.targets_info = targets_info;
 
       err = svn_wc_walk_status(ctx->wc_ctx, dir_abspath, svn_depth_infinity,
-                               TRUE, FALSE, FALSE, NULL,
+                               TRUE, FALSE, FALSE, ignores,
                                can_delete_callback, &cb,
                                ctx->cancel_func, ctx->cancel_baton,
                                iterpool);

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/ra.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/ra.c Mon Aug 19 11:21:01 2013
@@ -627,6 +627,9 @@ svn_client__repos_location_segments(apr_
  * END_REVNUM must be valid revision numbers except that END_REVNUM may
  * be SVN_INVALID_REVNUM if END_URL is NULL.
  *
+ * YOUNGEST_REV is the already retrieved youngest revision of the ra session,
+ * but can be SVN_INVALID_REVNUM if the value is not already retrieved.
+ *
  * RA_SESSION is an open RA session parented at URL.
  */
 static svn_error_t *
@@ -637,6 +640,7 @@ repos_locations(const char **start_url,
                 svn_revnum_t peg_revnum,
                 svn_revnum_t start_revnum,
                 svn_revnum_t end_revnum,
+                svn_revnum_t youngest_rev,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
@@ -644,9 +648,9 @@ repos_locations(const char **start_url,
   apr_array_header_t *revs;
   apr_hash_t *rev_locs;
 
-  SVN_ERR_ASSERT(peg_revnum != SVN_INVALID_REVNUM);
-  SVN_ERR_ASSERT(start_revnum != SVN_INVALID_REVNUM);
-  SVN_ERR_ASSERT(end_revnum != SVN_INVALID_REVNUM || end_url == NULL);
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(peg_revnum));
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start_revnum));
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(end_revnum) || end_url == NULL);
 
   /* Avoid a network request in the common easy case. */
   if (start_revnum == peg_revnum
@@ -661,6 +665,27 @@ repos_locations(const char **start_url,
 
   SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, scratch_pool));
 
+  /* Handle another common case: The repository root can't move */
+  if (! strcmp(repos_url, url))
+    {
+      if (! SVN_IS_VALID_REVNUM(youngest_rev))
+        SVN_ERR(svn_ra_get_latest_revnum(ra_session, &youngest_rev,
+                                         scratch_pool));
+
+      if (start_revnum > youngest_rev
+          || (SVN_IS_VALID_REVNUM(end_revnum) && (end_revnum > youngest_rev)))
+        return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+                                 _("No such revision %ld"),
+                                 (start_revnum > youngest_rev) 
+                                        ? start_revnum : end_revnum);
+
+      if (start_url)
+        *start_url = apr_pstrdup(result_pool, repos_url);
+      if (end_url)
+        *end_url = apr_pstrdup(result_pool, repos_url);
+      return SVN_NO_ERROR;
+    }
+
   revs = apr_array_make(scratch_pool, 2, sizeof(svn_revnum_t));
   APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum;
   if (end_revnum != start_revnum && end_revnum != SVN_INVALID_REVNUM)
@@ -716,7 +741,7 @@ svn_client__repos_location(svn_client__p
                                             peg_loc->url, scratch_pool));
   err = repos_locations(&op_url, NULL, ra_session,
                         peg_loc->url, peg_loc->rev,
-                        op_revnum, SVN_INVALID_REVNUM,
+                        op_revnum, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
                         result_pool, scratch_pool);
   SVN_ERR(svn_error_compose_create(
             err, svn_ra_reparent(ra_session, old_session_url, scratch_pool)));
@@ -856,29 +881,26 @@ svn_client__repos_locations(const char *
 
   SVN_ERR(repos_locations(start_url, end_url,
                           ra_session, url, peg_revnum,
-                          start_revnum, end_revnum,
+                          start_revnum, end_revnum, youngest_rev,
                           pool, subpool));
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }
 
-
 svn_error_t *
-svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
-                                         const svn_client__pathrev_t *loc1,
-                                         const svn_client__pathrev_t *loc2,
-                                         svn_ra_session_t *session,
-                                         svn_client_ctx_t *ctx,
-                                         apr_pool_t *result_pool,
-                                         apr_pool_t *scratch_pool)
+svn_client__calc_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+                                          const svn_client__pathrev_t *loc1,
+                                          apr_hash_t *history1,
+                                          svn_boolean_t has_rev_zero_history1,
+                                          const svn_client__pathrev_t *loc2,
+                                          apr_hash_t *history2,
+                                          svn_boolean_t has_rev_zero_history2,
+                                          apr_pool_t *result_pool,
+                                          apr_pool_t *scratch_pool)
 {
-  apr_pool_t *sesspool = NULL;
-  apr_hash_t *history1, *history2;
   apr_hash_index_t *hi;
   svn_revnum_t yc_revision = SVN_INVALID_REVNUM;
   const char *yc_relpath = NULL;
-  svn_boolean_t has_rev_zero_history1;
-  svn_boolean_t has_rev_zero_history2;
 
   if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0)
     {
@@ -886,32 +908,6 @@ svn_client__get_youngest_common_ancestor
       return SVN_NO_ERROR;
     }
 
-  /* Open an RA session for the two locations. */
-  if (session == NULL)
-    {
-      sesspool = svn_pool_create(scratch_pool);
-      SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx,
-                                          sesspool, sesspool));
-    }
-
-  /* We're going to cheat and use history-as-mergeinfo because it
-     saves us a bunch of annoying custom data comparisons and such. */
-  SVN_ERR(svn_client__get_history_as_mergeinfo(&history1,
-                                               &has_rev_zero_history1,
-                                               loc1,
-                                               SVN_INVALID_REVNUM,
-                                               SVN_INVALID_REVNUM,
-                                               session, ctx, scratch_pool));
-  SVN_ERR(svn_client__get_history_as_mergeinfo(&history2,
-                                               &has_rev_zero_history2,
-                                               loc2,
-                                               SVN_INVALID_REVNUM,
-                                               SVN_INVALID_REVNUM,
-                                               session, ctx, scratch_pool));
-  /* Close the ra session if we opened one. */
-  if (sesspool)
-    svn_pool_destroy(sesspool);
-
   /* Loop through the first location's history, check for overlapping
      paths and ranges in the second location's history, and
      remembering the youngest matching location. */
@@ -965,47 +961,62 @@ svn_client__get_youngest_common_ancestor
 }
 
 svn_error_t *
-svn_client__youngest_common_ancestor(const char **ancestor_url,
-                                     svn_revnum_t *ancestor_rev,
-                                     const char *path_or_url1,
-                                     const svn_opt_revision_t *revision1,
-                                     const char *path_or_url2,
-                                     const svn_opt_revision_t *revision2,
-                                     svn_client_ctx_t *ctx,
-                                     apr_pool_t *result_pool,
-                                     apr_pool_t *scratch_pool)
+svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
+                                         const svn_client__pathrev_t *loc1,
+                                         const svn_client__pathrev_t *loc2,
+                                         svn_ra_session_t *session,
+                                         svn_client_ctx_t *ctx,
+                                         apr_pool_t *result_pool,
+                                         apr_pool_t *scratch_pool)
 {
-  apr_pool_t *sesspool = svn_pool_create(scratch_pool);
-  svn_ra_session_t *session;
-  svn_client__pathrev_t *loc1, *loc2, *ancestor;
-
-  /* Resolve the two locations */
-  SVN_ERR(svn_client__ra_session_from_path2(&session, &loc1,
-                                            path_or_url1, NULL,
-                                            revision1, revision1,
-                                            ctx, sesspool));
-  SVN_ERR(svn_client__resolve_rev_and_url(&loc2, session,
-                                          path_or_url2, revision2, revision2,
-                                          ctx, scratch_pool));
-
-  SVN_ERR(svn_client__get_youngest_common_ancestor(
-            &ancestor, loc1, loc2, session, ctx, result_pool, scratch_pool));
+  apr_pool_t *sesspool = NULL;
+  apr_hash_t *history1, *history2;
+  svn_boolean_t has_rev_zero_history1;
+  svn_boolean_t has_rev_zero_history2;
 
-  if (ancestor)
+  if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0)
     {
-      *ancestor_url = ancestor->url;
-      *ancestor_rev = ancestor->rev;
+      *ancestor_p = NULL;
+      return SVN_NO_ERROR;
     }
-  else
+
+  /* Open an RA session for the two locations. */
+  if (session == NULL)
     {
-      *ancestor_url = NULL;
-      *ancestor_rev = SVN_INVALID_REVNUM;
+      sesspool = svn_pool_create(scratch_pool);
+      SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx,
+                                          sesspool, sesspool));
     }
-  svn_pool_destroy(sesspool);
+
+  /* We're going to cheat and use history-as-mergeinfo because it
+     saves us a bunch of annoying custom data comparisons and such. */
+  SVN_ERR(svn_client__get_history_as_mergeinfo(&history1,
+                                               &has_rev_zero_history1,
+                                               loc1,
+                                               SVN_INVALID_REVNUM,
+                                               SVN_INVALID_REVNUM,
+                                               session, ctx, scratch_pool));
+  SVN_ERR(svn_client__get_history_as_mergeinfo(&history2,
+                                               &has_rev_zero_history2,
+                                               loc2,
+                                               SVN_INVALID_REVNUM,
+                                               SVN_INVALID_REVNUM,
+                                               session, ctx, scratch_pool));
+  /* Close the ra session if we opened one. */
+  if (sesspool)
+    svn_pool_destroy(sesspool);
+
+  SVN_ERR(svn_client__calc_youngest_common_ancestor(ancestor_p,
+                                                    loc1, history1,
+                                                    has_rev_zero_history1,
+                                                    loc2, history2,
+                                                    has_rev_zero_history2,
+                                                    result_pool,
+                                                    scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
-
 struct ra_ev2_baton {
   /* The working copy context, from the client context.  */
   svn_wc_context_t *wc_ctx;

Modified: subversion/branches/move-tracking-1/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_client/switch.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_client/switch.c Mon Aug 19 11:21:01 2013
@@ -231,8 +231,6 @@ switch_internal(svn_revnum_t *result_rev
         yca = NULL; /* Not versioned */
       else
         {
-          /* ### It would be nice if this function could reuse the existing
-             ra session instead of opening two for its own use. */
           SVN_ERR(svn_client__get_youngest_common_ancestor(
                   &yca, switch_loc, target_base_loc, ra_session, ctx,
                   pool, pool));

Modified: subversion/branches/move-tracking-1/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_delta/compat.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_delta/compat.c Mon Aug 19 11:21:01 2013
@@ -218,6 +218,7 @@ locate_change(struct ev2_edit_baton *eb,
   change = apr_pcalloc(eb->edit_pool, sizeof(*change));
   change->changing = SVN_INVALID_REVNUM;
   change->deleting = SVN_INVALID_REVNUM;
+  change->kind = svn_node_unknown;
 
   svn_hash_sets(eb->changes, relpath, change);
 
@@ -439,8 +440,8 @@ process_actions(struct ev2_edit_baton *e
                                            change->changing, NULL, props));
       else
         SVN_ERR(svn_editor_alter_file(eb->editor, repos_relpath,
-                                      change->changing, props,
-                                      checksum, contents));
+                                      change->changing,
+                                      checksum, contents, props));
     }
 
   return SVN_NO_ERROR;
@@ -1182,9 +1183,9 @@ static svn_error_t *
 alter_file_cb(void *baton,
               const char *relpath,
               svn_revnum_t revision,
-              apr_hash_t *props,
               const svn_checksum_t *checksum,
               svn_stream_t *contents,
+              apr_hash_t *props,
               apr_pool_t *scratch_pool)
 {
   struct editor_baton *eb = baton;
@@ -1234,8 +1235,8 @@ static svn_error_t *
 alter_symlink_cb(void *baton,
                  const char *relpath,
                  svn_revnum_t revision,
-                 apr_hash_t *props,
                  const char *target,
+                 apr_hash_t *props,
                  apr_pool_t *scratch_pool)
 {
   /* ### should we verify the kind is truly a symlink?  */

Modified: subversion/branches/move-tracking-1/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_delta/editor.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_delta/editor.c Mon Aug 19 11:21:01 2013
@@ -683,9 +683,9 @@ svn_error_t *
 svn_editor_alter_file(svn_editor_t *editor,
                       const char *relpath,
                       svn_revnum_t revision,
-                      apr_hash_t *props,
                       const svn_checksum_t *checksum,
-                      svn_stream_t *contents)
+                      svn_stream_t *contents,
+                      apr_hash_t *props)
 {
   svn_error_t *err = SVN_NO_ERROR;
 
@@ -705,8 +705,8 @@ svn_editor_alter_file(svn_editor_t *edit
     {
       START_CALLBACK(editor);
       err = editor->funcs.cb_alter_file(editor->baton,
-                                        relpath, revision, props,
-                                        checksum, contents,
+                                        relpath, revision,
+                                        checksum, contents, props,
                                         editor->scratch_pool);
       END_CALLBACK(editor);
     }
@@ -723,8 +723,8 @@ svn_error_t *
 svn_editor_alter_symlink(svn_editor_t *editor,
                          const char *relpath,
                          svn_revnum_t revision,
-                         apr_hash_t *props,
-                         const char *target)
+                         const char *target,
+                         apr_hash_t *props)
 {
   svn_error_t *err = SVN_NO_ERROR;
 
@@ -740,8 +740,8 @@ svn_editor_alter_symlink(svn_editor_t *e
     {
       START_CALLBACK(editor);
       err = editor->funcs.cb_alter_symlink(editor->baton,
-                                           relpath, revision, props,
-                                           target,
+                                           relpath, revision,
+                                           target, props,
                                            editor->scratch_pool);
       END_CALLBACK(editor);
     }

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs/editor.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs/editor.c Mon Aug 19 11:21:01 2013
@@ -488,9 +488,9 @@ static svn_error_t *
 alter_file_cb(void *baton,
               const char *relpath,
               svn_revnum_t revision,
-              apr_hash_t *props,
               const svn_checksum_t *checksum,
               svn_stream_t *contents,
+              apr_hash_t *props,
               apr_pool_t *scratch_pool)
 {
   struct edit_baton *eb = baton;
@@ -521,8 +521,8 @@ static svn_error_t *
 alter_symlink_cb(void *baton,
                  const char *relpath,
                  svn_revnum_t revision,
-                 apr_hash_t *props,
                  const char *target,
+                 apr_hash_t *props,
                  apr_pool_t *scratch_pool)
 {
   struct edit_baton *eb = baton;

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.c Mon Aug 19 11:21:01 2013
@@ -481,7 +481,12 @@ svn_fs_open(svn_fs_t **fs_p, const char 
 }
 
 svn_error_t *
-svn_fs_upgrade(const char *path, apr_pool_t *pool)
+svn_fs_upgrade2(const char *path,
+                svn_fs_upgrade_notify_t notify_func,
+                void *notify_baton,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
+                apr_pool_t *pool)
 {
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
@@ -490,11 +495,20 @@ svn_fs_upgrade(const char *path, apr_poo
   fs = fs_new(NULL, pool);
 
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
-                       vtable->upgrade_fs(fs, path, pool, common_pool));
+                       vtable->upgrade_fs(fs, path,
+                                          notify_func, notify_baton,
+                                          cancel_func, cancel_baton,
+                                          pool, common_pool));
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
+svn_fs_upgrade(const char *path, apr_pool_t *pool)
+{
+  return svn_error_trace(svn_fs_upgrade2(path, NULL, NULL, NULL, NULL, pool));
+}
+
+svn_error_t *
 svn_fs_verify(const char *path,
               apr_hash_t *fs_config,
               svn_revnum_t start,

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.h?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs/fs-loader.h Mon Aug 19 11:21:01 2013
@@ -85,7 +85,13 @@ typedef struct fs_library_vtable_t
   svn_error_t *(*open_fs_for_recovery)(svn_fs_t *fs, const char *path,
                                        apr_pool_t *pool,
                                        apr_pool_t *common_pool);
-  svn_error_t *(*upgrade_fs)(svn_fs_t *fs, const char *path, apr_pool_t *pool,
+  svn_error_t *(*upgrade_fs)(svn_fs_t *fs,
+                             const char *path,
+                             svn_fs_upgrade_notify_t notify_func,
+                             void *notify_baton,
+                             svn_cancel_func_t cancel_func,
+                             void *cancel_baton,
+                             apr_pool_t *pool,
                              apr_pool_t *common_pool);
   svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
                             svn_revnum_t start,

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_base/bdb/env.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_base/bdb/env.c Mon Aug 19 11:21:01 2013
@@ -227,7 +227,7 @@ bdb_error_gatherer(const DB_ENV *dbenv, 
 
   SVN_BDB_ERROR_GATHERER_IGNORE(dbenv);
 
-  new_err = svn_error_createf(APR_SUCCESS, NULL, "bdb: %s", msg);
+  new_err = svn_error_createf(SVN_ERR_FS_BERKELEY_DB, NULL, "bdb: %s", msg);
   if (error_info->pending_errors)
     svn_error_compose(error_info->pending_errors, new_err);
   else

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_base/fs.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_base/fs.c Mon Aug 19 11:21:01 2013
@@ -898,7 +898,13 @@ base_open_for_recovery(svn_fs_t *fs, con
 }
 
 static svn_error_t *
-base_upgrade(svn_fs_t *fs, const char *path, apr_pool_t *pool,
+base_upgrade(svn_fs_t *fs,
+             const char *path,
+             svn_fs_upgrade_notify_t notify_func,
+             void *notify_baton,
+             svn_cancel_func_t cancel_func,
+             void *cancel_baton,
+             apr_pool_t *pool,
              apr_pool_t *common_pool)
 {
   const char *version_file_path;
@@ -921,6 +927,9 @@ base_upgrade(svn_fs_t *fs, const char *p
   /* Bump the format file's stored version number. */
   SVN_ERR(svn_io_write_version_file(version_file_path,
                                     SVN_FS_BASE__FORMAT_NUMBER, pool));
+  if (notify_func)
+    SVN_ERR(notify_func(notify_baton, SVN_FS_BASE__FORMAT_NUMBER,
+                        svn_fs_upgrade_format_bumped, pool));
 
   /* Check and see if we need to record the "bump" revision. */
   if (old_format_number < SVN_FS_BASE__MIN_FORWARD_DELTAS_FORMAT)

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_base/tree.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_base/tree.c Mon Aug 19 11:21:01 2013
@@ -4811,6 +4811,13 @@ base_node_origin_rev(svn_revnum_t *revis
      prev_location() does below will work. */
   path = svn_fs__canonicalize_abspath(path, pool);
 
+  /* Special-case the root node (for performance reasons) */
+  if (strcmp(path, "/") == 0)
+    {
+      *revision = 0;
+      return SVN_NO_ERROR;
+    }
+
   /* If we have support for the node-origins table, we'll try to use
      it. */
   if (bfd->format >= SVN_FS_BASE__MIN_NODE_ORIGINS_FORMAT)

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/caching.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/caching.c Mon Aug 19 11:21:01 2013
@@ -210,9 +210,10 @@ dump_cache_statistics(void *baton_void)
                                          TRUE,
                                          baton->pool);
 
-  if (! err)
+  /* skip unused caches */
+  if (! err && (info.gets > 0 || info.sets > 0))
     {
-      text_stats = svn_cache__format_info(&info, baton->pool);
+      text_stats = svn_cache__format_info(&info, TRUE, baton->pool);
       lines = svn_cstring_split(text_stats->data, "\n", FALSE, baton->pool);
 
       for (i = 0; i < lines->nelts; ++i)
@@ -233,6 +234,29 @@ dump_cache_statistics(void *baton_void)
 
   return result;
 }
+
+static apr_status_t
+dump_global_cache_statistics(void *baton_void)
+{
+  apr_pool_t *pool = baton_void;
+
+  svn_cache__info_t *info = svn_cache__membuffer_get_global_info(pool);
+  svn_string_t *text_stats = svn_cache__format_info(info, FALSE, pool);
+  apr_array_header_t *lines = svn_cstring_split(text_stats->data, "\n",
+                                                FALSE, pool);
+
+  int i;
+  for (i = 0; i < lines->nelts; ++i)
+    {
+      const char *line = APR_ARRAY_IDX(lines, i, const char *);
+#ifdef SVN_DEBUG
+      SVN_DBG(("%s\n", line));
+#endif
+    }
+
+  return APR_SUCCESS;
+}
+
 #endif /* SVN_DEBUG_CACHE_DUMP_STATS */
 
 /* This function sets / registers the required callbacks for a given
@@ -369,6 +393,18 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
   membuffer = svn_cache__get_global_membuffer_cache();
 
+#ifdef SVN_DEBUG_CACHE_DUMP_STATS
+
+  /* schedule printing the global access statistics upon pool cleanup,
+    * i.e. end of FSFS session.
+    */
+  if (membuffer)
+    apr_pool_cleanup_register(pool,
+                              pool,
+                              dump_global_cache_statistics,
+                              apr_pool_cleanup_null);
+#endif
+
   /* Make the cache for revision roots.  For the vast majority of
    * commands, this is only going to contain a few entries (svnadmin
    * dump/verify is an exception here), so to reduce overhead let's

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.c Mon Aug 19 11:21:01 2013
@@ -289,7 +289,13 @@ fs_open_for_recovery(svn_fs_t *fs,
 
 /* This implements the fs_library_vtable_t.upgrade_fs() API. */
 static svn_error_t *
-fs_upgrade(svn_fs_t *fs, const char *path, apr_pool_t *pool,
+fs_upgrade(svn_fs_t *fs,
+           const char *path,
+           svn_fs_upgrade_notify_t notify_func,
+           void *notify_baton,
+           svn_cancel_func_t cancel_func,
+           void *cancel_baton,
+           apr_pool_t *pool,
            apr_pool_t *common_pool)
 {
   SVN_ERR(svn_fs__check_fs(fs, FALSE));
@@ -297,7 +303,8 @@ fs_upgrade(svn_fs_t *fs, const char *pat
   SVN_ERR(svn_fs_fs__open(fs, path, pool));
   SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
   SVN_ERR(fs_serialized_init(fs, common_pool, pool));
-  return svn_fs_fs__upgrade(fs, pool);
+  return svn_fs_fs__upgrade(fs, notify_func, notify_baton,
+                            cancel_func, cancel_baton, pool);
 }
 
 static svn_error_t *

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.h?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs.h Mon Aug 19 11:21:01 2013
@@ -221,7 +221,11 @@ typedef struct fs_fs_shared_data_t
 /* Data structure for the 1st level DAG node cache. */
 typedef struct fs_fs_dag_cache_t fs_fs_dag_cache_t;
 
-/* Key type for all caches that use revision + offset / counter as key. */
+/* Key type for all caches that use revision + offset / counter as key.
+
+   NOTE: always initialize this using calloc() or '= {0};'!  This is used
+   as a cahe key and the padding bytes on 32 bit archs should be zero for
+   cache effectiveness. */
 typedef struct pair_cache_key_t
 {
   svn_revnum_t revision;

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.c Mon Aug 19 11:21:01 2013
@@ -484,6 +484,7 @@ path_and_offset_of(apr_file_t *file, apr
 
 
 
+
 /* Functions for working with shared transaction data. */
 
 /* Return the transaction object for transaction TXN_ID from the
@@ -1460,10 +1461,21 @@ delete_revprops_shard(const char *shard_
                       apr_pool_t *scratch_pool);
 
 /* In the filesystem FS, pack all revprop shards up to min_unpacked_rev.
- * Use SCRATCH_POOL for temporary allocations.
+ * 
+ * NOTE: Keep the old non-packed shards around until after the format bump.
+ * Otherwise, re-running upgrade will drop the packed revprop shard but
+ * have no unpacked data anymore.  Call upgrade_cleanup_pack_revprops after
+ * the bump.
+ * 
+ * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are
+ * used in the usual way.  Temporary allocations are done in SCRATCH_POOL.
  */
 static svn_error_t *
 upgrade_pack_revprops(svn_fs_t *fs,
+                      svn_fs_upgrade_notify_t notify_func,
+                      void *notify_baton,
+                      svn_cancel_func_t cancel_func,
+                      void *cancel_baton,
                       apr_pool_t *scratch_pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -1496,10 +1508,47 @@ upgrade_pack_revprops(svn_fs_t *fs,
                                   shard, ffd->max_files_per_dir,
                                   (int)(0.9 * ffd->revprop_pack_size),
                                   compression_level,
-                                  NULL, NULL, iterpool));
+                                  cancel_func, cancel_baton, iterpool));
+      if (notify_func)
+        SVN_ERR(notify_func(notify_baton, shard,
+                            svn_fs_upgrade_pack_revprops, iterpool));
+
       svn_pool_clear(iterpool);
     }
 
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* In the filesystem FS, remove all non-packed revprop shards up to
+ * min_unpacked_rev.  Temporary allocations are done in SCRATCH_POOL.
+ * 
+ * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are
+ * used in the usual way.  Cancellation is supported in the sense that we
+ * will cleanly abort the operation.  However, there will be remnant shards
+ * that must be removed manually.
+ *
+ * See upgrade_pack_revprops for more info.
+ */
+static svn_error_t *
+upgrade_cleanup_pack_revprops(svn_fs_t *fs,
+                              svn_fs_upgrade_notify_t notify_func,
+                              void *notify_baton,
+                              svn_cancel_func_t cancel_func,
+                              void *cancel_baton,
+                              apr_pool_t *scratch_pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  const char *revprops_shard_path;
+  apr_int64_t shard;
+  apr_int64_t first_unpacked_shard
+    =  ffd->min_unpacked_rev / ffd->max_files_per_dir;
+
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  const char *revsprops_dir = svn_dirent_join(fs->path, PATH_REVPROPS_DIR,
+                                              scratch_pool);
+  
   /* delete the non-packed revprops shards afterwards */
   for (shard = 0; shard < first_unpacked_shard; ++shard)
     {
@@ -1508,7 +1557,11 @@ upgrade_pack_revprops(svn_fs_t *fs,
                        iterpool);
       SVN_ERR(delete_revprops_shard(revprops_shard_path,
                                     shard, ffd->max_files_per_dir,
-                                    NULL, NULL, iterpool));
+                                    cancel_func, cancel_baton, iterpool));
+      if (notify_func)
+        SVN_ERR(notify_func(notify_baton, shard,
+                            svn_fs_upgrade_cleanup_revprops, iterpool));
+
       svn_pool_clear(iterpool);
     }
 
@@ -1517,13 +1570,26 @@ upgrade_pack_revprops(svn_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Baton type bridging svn_fs_fs__upgrade and upgrade_body carrying 
+ * parameters over between them. */
+struct upgrade_baton_t
+{
+  svn_fs_t *fs;
+  svn_fs_upgrade_notify_t notify_func;
+  void *notify_baton;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+};
+
 static svn_error_t *
 upgrade_body(void *baton, apr_pool_t *pool)
 {
-  svn_fs_t *fs = baton;
+  struct upgrade_baton_t *upgrade_baton = baton;
+  svn_fs_t *fs = upgrade_baton->fs;
   int format, max_files_per_dir;
   const char *format_path = path_format(fs, pool);
   svn_node_kind_t kind;
+  svn_boolean_t needs_revprop_shard_cleanup = FALSE;
 
   /* Read the FS format number and max-files-per-dir setting. */
   SVN_ERR(read_format(&format, &max_files_per_dir, format_path, pool));
@@ -1575,22 +1641,62 @@ upgrade_body(void *baton, apr_pool_t *po
   if (format < SVN_FS_FS__MIN_PACKED_FORMAT)
     SVN_ERR(svn_io_file_create(path_min_unpacked_rev(fs, pool), "0\n", pool));
 
-  /* If the file system supports revision packing but not revprop packing,
-     pack the revprops up to the point that revision data has been packed. */
+  /* If the file system supports revision packing but not revprop packing
+     *and* the FS has been sharded, pack the revprops up to the point that
+     revision data has been packed.  However, keep the non-packed revprop
+     files around until after the format bump */
   if (   format >= SVN_FS_FS__MIN_PACKED_FORMAT
-      && format < SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
-    SVN_ERR(upgrade_pack_revprops(fs, pool));
+      && format < SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT
+      && max_files_per_dir > 0)
+    {
+      needs_revprop_shard_cleanup = TRUE;
+      SVN_ERR(upgrade_pack_revprops(fs,
+                                    upgrade_baton->notify_func,
+                                    upgrade_baton->notify_baton,
+                                    upgrade_baton->cancel_func,
+                                    upgrade_baton->cancel_baton,
+                                    pool));
+    }
 
   /* Bump the format file. */
-  return write_format(format_path, SVN_FS_FS__FORMAT_NUMBER, max_files_per_dir,
-                      TRUE, pool);
+  SVN_ERR(write_format(format_path, SVN_FS_FS__FORMAT_NUMBER,
+                       max_files_per_dir, TRUE, pool));
+  if (upgrade_baton->notify_func)
+    SVN_ERR(upgrade_baton->notify_func(upgrade_baton->notify_baton,
+                                       SVN_FS_FS__FORMAT_NUMBER,
+                                       svn_fs_upgrade_format_bumped,
+                                       pool));
+
+  /* Now, it is safe to remove the redundant revprop files. */
+  if (needs_revprop_shard_cleanup)
+    SVN_ERR(upgrade_cleanup_pack_revprops(fs,
+                                          upgrade_baton->notify_func,
+                                          upgrade_baton->notify_baton,
+                                          upgrade_baton->cancel_func,
+                                          upgrade_baton->cancel_baton,
+                                          pool));
+
+  /* Done */
+  return SVN_NO_ERROR;
 }
 
 
 svn_error_t *
-svn_fs_fs__upgrade(svn_fs_t *fs, apr_pool_t *pool)
+svn_fs_fs__upgrade(svn_fs_t *fs,
+                   svn_fs_upgrade_notify_t notify_func,
+                   void *notify_baton,
+                   svn_cancel_func_t cancel_func,
+                   void *cancel_baton,
+                   apr_pool_t *pool)
 {
-  return svn_fs_fs__with_write_lock(fs, upgrade_body, (void *)fs, pool);
+  struct upgrade_baton_t baton;
+  baton.fs = fs;
+  baton.notify_func = notify_func;
+  baton.notify_baton = notify_baton;
+  baton.cancel_func = cancel_func;
+  baton.cancel_baton = cancel_baton;
+  
+  return svn_fs_fs__with_write_lock(fs, upgrade_body, (void *)&baton, pool);
 }
 
 
@@ -3202,7 +3308,7 @@ ensure_revprop_generation(svn_fs_t *fs, 
   SVN_ERR(ensure_revprop_namespace(fs));
   if (ffd->revprop_generation == NULL)
     {
-      apr_int64_t current = 0;
+      apr_int64_t current;
 
       SVN_ERR(svn_named_atomic__get(&ffd->revprop_generation,
                                     ffd->revprop_namespace,
@@ -3242,15 +3348,17 @@ ensure_revprop_timeout(svn_fs_t *fs)
 }
 
 /* Create an error object with the given MESSAGE and pass it to the
-   WARNING member of FS. */
+   WARNING member of FS. Clears UNDERLYING_ERR. */
 static void
 log_revprop_cache_init_warning(svn_fs_t *fs,
                                svn_error_t *underlying_err,
-                               const char *message)
+                               const char *message,
+                               apr_pool_t *pool)
 {
-  svn_error_t *err = svn_error_createf(SVN_ERR_FS_REVPROP_CACHE_INIT_FAILURE,
-                                       underlying_err,
-                                       message, fs->path);
+  svn_error_t *err = svn_error_createf(
+                       SVN_ERR_FS_REVPROP_CACHE_INIT_FAILURE,
+                       underlying_err, message,
+                       svn_dirent_local_style(fs->path, pool));
 
   if (fs->warning)
     (fs->warning)(fs->warning_baton, err);
@@ -3279,7 +3387,8 @@ has_revprop_cache(svn_fs_t *fs, apr_pool
       ffd->revprop_cache = NULL;
       log_revprop_cache_init_warning(fs, NULL,
                                      "Revprop caching for '%s' disabled"
-                                     " because it would be inefficient.");
+                                     " because it would be inefficient.",
+                                     pool);
 
       return FALSE;
     }
@@ -3294,7 +3403,8 @@ has_revprop_cache(svn_fs_t *fs, apr_pool
       log_revprop_cache_init_warning(fs, error,
                                      "Revprop caching for '%s' disabled "
                                      "because SHM infrastructure for revprop "
-                                     "caching failed to initialize.");
+                                     "caching failed to initialize.",
+                                     pool);
 
       return FALSE;
     }
@@ -3315,9 +3425,9 @@ typedef struct revprop_generation_fixup_
 /* If the revprop generation has an odd value, it means the original writer
    of the revprop got killed. We don't know whether that process as able
    to change the revprop data but we assume that it was. Therefore, we
-   increase the generation in that case to basically invalidate everyones
+   increase the generation in that case to basically invalidate everyone's
    cache content.
-   Execute this onlx while holding the write lock to the repo in baton->FFD.
+   Execute this only while holding the write lock to the repo in baton->FFD.
  */
 static svn_error_t *
 revprop_generation_fixup(void *void_baton,
@@ -3618,7 +3728,7 @@ get_revprop_packname(svn_fs_t *fs,
 
   if (revprops->manifest->nelts <= idx)
     return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                             _("Packed revprop manifest for rev %ld too "
+                             _("Packed revprop manifest for r%ld too "
                                "small"), revprops->revision);
 
   /* Now get the file name */
@@ -3652,7 +3762,7 @@ parse_packed_revprops(svn_fs_t *fs,
   svn_string_t *compressed
       = svn_stringbuf__morph_into_string(revprops->packed_revprops);
   svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(pool);
-  SVN_ERR(svn__decompress(compressed, uncompressed, 0x1000000));
+  SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX));
 
   /* read first revision number and number of revisions in the pack */
   stream = svn_stream_from_stringbuf(uncompressed, scratch_pool);
@@ -3791,14 +3901,14 @@ read_pack_revprop(packed_revprops_t **re
   /* the file content should be available now */
   if (!result->packed_revprops)
     return svn_error_createf(SVN_ERR_FS_PACKED_REVPROP_READ_FAILURE, NULL,
-                  _("Failed to read revprop pack file for rev %ld"), rev);
+                  _("Failed to read revprop pack file for r%ld"), rev);
 
   /* parse it. RESULT will be complete afterwards. */
   err = parse_packed_revprops(fs, result, pool, iterpool);
   svn_pool_destroy(iterpool);
   if (err)
     return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
-                  _("Revprop pack file for rev %ld is corrupt"), rev);
+                  _("Revprop pack file for r%ld is corrupt"), rev);
 
   *revprops = result;
 
@@ -4926,7 +5036,6 @@ get_combined_window(svn_stringbuf_t **re
 {
   apr_pool_t *pool, *new_pool, *window_pool;
   int i;
-  svn_txdelta_window_t *window;
   apr_array_header_t *windows;
   svn_stringbuf_t *source, *buf = rb->base_window;
   struct rep_state *rs;
@@ -4939,6 +5048,8 @@ get_combined_window(svn_stringbuf_t **re
   windows = apr_array_make(window_pool, 0, sizeof(svn_txdelta_window_t *));
   for (i = 0; i < rb->rs_list->nelts; ++i)
     {
+      svn_txdelta_window_t *window;
+
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
       SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool));
 
@@ -4954,6 +5065,7 @@ get_combined_window(svn_stringbuf_t **re
   pool = svn_pool_create(rb->pool);
   for (--i; i >= 0; --i)
     {
+      svn_txdelta_window_t *window;
 
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
       window = APR_ARRAY_IDX(windows, i, svn_txdelta_window_t *);
@@ -7089,7 +7201,12 @@ choose_delta_base(representation_t **rep
                   svn_boolean_t props,
                   apr_pool_t *pool)
 {
+  /* The zero-based index (counting from the "oldest" end), along NODEREVs line
+   * predecessors, of the node-rev we will use as delta base. */
   int count;
+  /* The length of the linear part of a delta chain.  (Delta chains use
+   * skip-delta bits for the high-order bits and are linear in the low-order
+   * bits.) */
   int walk;
   node_revision_t *base;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -7143,6 +7260,8 @@ choose_delta_base(representation_t **rep
        * Please note that copied nodes - such as branch directories - will
        * look the same (false positive) while reps shared within the same
        * revision will not be caught (false negative).
+       *
+       * Message-ID: <CA+t0gk1wzitkih3GRCLDvK-bTEm=hgppGb_7xXMtvuXDYPfL+Q@mail.gmail.com>
        */
       if (props)
         {
@@ -7161,7 +7280,7 @@ choose_delta_base(representation_t **rep
   /* return a suitable base representation */
   *rep = props ? base->prop_rep : base->data_rep;
 
-  /* if we encountered a shared rep, it's parent chain may be different
+  /* if we encountered a shared rep, its parent chain may be different
    * from the node-rev parent chain. */
   if (*rep && maybe_shared_rep)
     {
@@ -7209,7 +7328,6 @@ choose_delta_base(representation_t **rep
       svn_pool_destroy(sub_pool);
     }
 
-  /* verify that the reps don't form a degenerated '*/
   return SVN_NO_ERROR;
 }
 
@@ -7327,7 +7445,7 @@ rep_write_get_baton(struct rep_write_bat
   return SVN_NO_ERROR;
 }
 
-/* For the hash REP->SHA1, try to find an already existing representation
+/* For REP->SHA1_CHECKSUM, try to find an already existing representation
    in FS and return it in *OUT_REP.  If no such representation exists or
    if rep sharing has been disabled for FS, NULL will be returned.  Since
    there may be new duplicate representations within the same uncommitted
@@ -8173,12 +8291,9 @@ write_final_changed_path_info(apr_off_t 
   sorted_changed_paths = svn_sort__hash(changed_paths,
                                         svn_sort_compare_items_lexically, pool);
 
-  /* Iterate through the changed paths one at a time, and convert the
-     temporary node-id into a permanent one for each change entry. */
+  /* Write all items to disk in the new order. */
   for (i = 0; i < sorted_changed_paths->nelts; ++i)
     {
-      node_revision_t *noderev;
-      const svn_fs_id_t *id;
       svn_fs_path_change2_t *change;
       const char *path;
 
@@ -8187,21 +8302,6 @@ write_final_changed_path_info(apr_off_t 
       change = APR_ARRAY_IDX(sorted_changed_paths, i, svn_sort__item_t).value;
       path = APR_ARRAY_IDX(sorted_changed_paths, i, svn_sort__item_t).key;
 
-      id = change->node_rev_id;
-
-      /* If this was a delete of a mutable node, then it is OK to
-         leave the change entry pointing to the non-existent temporary
-         node, since it will never be used. */
-      if ((change->change_kind != svn_fs_path_change_delete) &&
-          (! svn_fs_fs__id_txn_id(id)))
-        {
-          SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, id, iterpool));
-
-          /* noderev has the permanent node-id at this point, so we just
-             substitute it for the temporary one. */
-          change->node_rev_id = noderev->id;
-        }
-
       /* Write out the new entry into the final rev-file. */
       SVN_ERR(write_change_entry(file, path, change, include_node_kinds,
                                  iterpool));
@@ -9995,6 +10095,9 @@ pack_revprops_shard(const char *pack_fil
   end_rev = (svn_revnum_t) ((shard + 1) * (max_files_per_dir) - 1);
   if (start_rev == 0)
     ++start_rev;
+    /* Special special case: if max_files_per_dir is 1, then at this point
+       start_rev == 1 and end_rev == 0 (!).  Fortunately, everything just
+       works. */
 
   /* initialize the revprop size info */
   sizes = apr_array_make(scratch_pool, max_files_per_dir, sizeof(apr_off_t));
@@ -10176,13 +10279,31 @@ pack_shard(const char *revs_dir,
                             (svn_revnum_t)((shard + 1) * max_files_per_dir),
                             pool));
 
-  /* Finally, remove the existing shard directories. */
+  /* Finally, remove the existing shard directories.
+   * For revprops, clean up older obsolete shards as well as they might
+   * have been left over from an interrupted FS upgrade. */
   SVN_ERR(svn_io_remove_dir2(rev_shard_path, TRUE,
                              cancel_func, cancel_baton, pool));
   if (revsprops_dir)
-    SVN_ERR(delete_revprops_shard(revprops_shard_path,
-                                  shard, max_files_per_dir,
-                                  cancel_func, cancel_baton, pool));
+    {
+      svn_node_kind_t kind = svn_node_dir;
+      apr_int64_t to_cleanup = shard;
+      do
+        {
+          SVN_ERR(delete_revprops_shard(revprops_shard_path,
+                                        to_cleanup, max_files_per_dir,
+                                        cancel_func, cancel_baton, pool));
+
+          /* If the previous shard exists, clean it up as well.
+             Don't try to clean up shard 0 as it we can't tell quickly
+             whether it actually needs cleaning up. */
+          revprops_shard_path = svn_dirent_join(revsprops_dir,
+                      apr_psprintf(pool, "%" APR_INT64_T_FMT, --to_cleanup),
+                      pool);
+          SVN_ERR(svn_io_check_path(revprops_shard_path, &kind, pool));
+        }
+      while (kind == svn_node_dir && to_cleanup > 0);
+    }
 
   /* Notify caller we're starting to pack this shard. */
   if (notify_func)

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.h?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/fs_fs.h Mon Aug 19 11:21:01 2013
@@ -34,8 +34,15 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *f
                              const char *path,
                              apr_pool_t *pool);
 
-/* Upgrade the fsfs filesystem FS.  Use POOL for temporary allocations. */
+/* Upgrade the fsfs filesystem FS.  Indicate progress via the optional
+ * NOTIFY_FUNC callback using NOTIFY_BATON.  The optional CANCEL_FUNC
+ * will periodically be called with CANCEL_BATON to allow for preemption.
+ * Use POOL for temporary allocations. */
 svn_error_t *svn_fs_fs__upgrade(svn_fs_t *fs,
+                                svn_fs_upgrade_notify_t notify_func,
+                                void *notify_baton,
+                                svn_cancel_func_t cancel_func,
+                                void *cancel_baton,
                                 apr_pool_t *pool);
 
 /* Verify metadata in fsfs filesystem FS.  Limit the checks to revisions

Modified: subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/tree.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_fs_fs/tree.c Mon Aug 19 11:21:01 2013
@@ -151,7 +151,7 @@ typedef struct cache_entry_t
 {
   /* hash value derived from PATH, REVISION.
      Used to short-circuit failed lookups. */
-  long int hash_value;
+  apr_uint32_t hash_value;
 
   /* revision to which the NODE belongs */
   svn_revnum_t revision;
@@ -340,7 +340,12 @@ cache_lookup( fs_fs_dag_cache_t *cache
 {
   apr_size_t i, bucket_index;
   apr_size_t path_len = strlen(path);
-  long int hash_value = revision;
+  apr_uint32_t hash_value = (apr_uint32_t)revision;
+
+#if SVN_UNALIGNED_ACCESS_IS_OK
+  /* "randomizing" / distributing factor used in our hash function */
+  const apr_uint32_t factor = 0xd1f3da69;
+#endif
 
   /* optimistic lookup: hit the same bucket again? */
   cache_entry_t *result = &cache->buckets[cache->last_hit];
@@ -353,11 +358,25 @@ cache_lookup( fs_fs_dag_cache_t *cache
 
   /* need to do a full lookup.  Calculate the hash value
      (HASH_VALUE has been initialized to REVISION). */
-  for (i = 0; i + 4 <= path_len; i += 4)
-    hash_value = hash_value * 0xd1f3da69 + *(const apr_uint32_t*)(path + i);
+  i = 0;
+#if SVN_UNALIGNED_ACCESS_IS_OK
+  /* We relax the dependency chain between iterations by processing
+     two chunks from the input per hash_value self-multiplication.
+     The HASH_VALUE update latency is now 1 MUL latency + 1 ADD latency
+     per 2 chunks instead of 1 chunk.
+   */
+  for (; i + 8 <= path_len; i += 8)
+    hash_value = hash_value * factor * factor
+               + (  *(const apr_uint32_t*)(path + i) * factor
+                  + *(const apr_uint32_t*)(path + i + 4));
+#endif
 
   for (; i < path_len; ++i)
-    hash_value = hash_value * 33 + path[i];
+    /* Help GCC to minimize the HASH_VALUE update latency by splitting the
+       MUL 33 of the naive implementation: h = h * 33 + path[i].  This
+       shortens the dependency chain from 1 shift + 2 ADDs to 1 shift + 1 ADD.
+     */
+    hash_value = hash_value * 32 + (hash_value + (unsigned char)path[i]);
 
   bucket_index = hash_value + (hash_value >> 16);
   bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT;
@@ -3402,6 +3421,14 @@ fs_node_origin_rev(svn_revnum_t *revisio
       return SVN_NO_ERROR;
     }
 
+  /* The root node always has ID 0, created in revision 0 and will never
+     use the new-style ID format. */
+  if (strcmp(node_id, "0") == 0)
+    {
+      *revision = 0;
+      return SVN_NO_ERROR;
+    }
+
   /* OK, it's an old-style ID?  Maybe it's cached. */
   SVN_ERR(svn_fs_fs__get_node_origin(&cached_origin_id,
                                      fs,

Modified: subversion/branches/move-tracking-1/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/subversion/libsvn_ra/ra_loader.c?rev=1515362&r1=1515361&r2=1515362&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/move-tracking-1/subversion/libsvn_ra/ra_loader.c Mon Aug 19 11:21:01 2013
@@ -1030,6 +1030,13 @@ svn_error_t *svn_ra_get_file_revs2(svn_r
   if (include_merged_revisions)
     SVN_ERR(svn_ra__assert_mergeinfo_capable_server(session, NULL, pool));
 
+  if (start > end)
+    SVN_ERR(
+     svn_ra__assert_capable_server(session,
+                                   SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+                                   NULL,
+                                   pool));
+
   err = session->vtable->get_file_revs(session, path, start, end,
                                        include_merged_revisions,
                                        handler, handler_baton, pool);



Mime
View raw message