subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1329209 [30/38] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/client-side/vim/ contrib/server-side/mod_dontdothat/ notes/ notes/a...
Date Mon, 23 Apr 2012 12:33:03 GMT
Modified: subversion/branches/javahl-ra/subversion/svn/proplist-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/proplist-cmd.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/proplist-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/proplist-cmd.c Mon Apr 23 12:32:48 2012
@@ -223,12 +223,12 @@ svn_cl__proplist(apr_getopt_t *os,
       if (errors->nelts > 0)
         {
           svn_error_t *err;
-          
+
           err = svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL, NULL);
           for (i = 0; i < errors->nelts; i++)
             {
               apr_status_t status = APR_ARRAY_IDX(errors, i, apr_status_t);
-              
+
               if (status == SVN_ERR_ENTRY_NOT_FOUND)
                 err = svn_error_quick_wrap(err,
                                            _("Could not display properties "

Modified: subversion/branches/javahl-ra/subversion/svn/status-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/status-cmd.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/status-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/status-cmd.c Mon Apr 23 12:32:48 2012
@@ -50,6 +50,8 @@ struct status_baton
 {
   /* These fields all correspond to the ones in the
      svn_cl__print_status() interface. */
+  const char *cwd_abspath;
+  svn_boolean_t suppress_externals_placeholders;
   svn_boolean_t detailed;
   svn_boolean_t show_last_committed;
   svn_boolean_t skip_unrecognized;
@@ -149,9 +151,12 @@ print_status_normal_or_xml(void *baton,
   struct status_baton *sb = baton;
 
   if (sb->xml_mode)
-    return svn_cl__print_status_xml(path, status, sb->ctx, pool);
+    return svn_cl__print_status_xml(sb->cwd_abspath, path, status,
+                                    sb->ctx, pool);
   else
-    return svn_cl__print_status(path, status, sb->detailed,
+    return svn_cl__print_status(sb->cwd_abspath, path, status,
+                                sb->suppress_externals_placeholders,
+                                sb->detailed,
                                 sb->show_last_committed,
                                 sb->skip_unrecognized,
                                 sb->repos_locks,
@@ -298,6 +303,9 @@ svn_cl__status(apr_getopt_t *os,
                                   "mode"));
     }
 
+  SVN_ERR(svn_dirent_get_absolute(&(sb.cwd_abspath), "", scratch_pool));
+  sb.suppress_externals_placeholders = (opt_state->quiet
+                                        && (! opt_state->verbose));
   sb.detailed = (opt_state->verbose || opt_state->update);
   sb.show_last_committed = opt_state->verbose;
   sb.skip_unrecognized = opt_state->quiet;

Modified: subversion/branches/javahl-ra/subversion/svn/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/status.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/status.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/status.c Mon Apr 23 12:32:48 2012
@@ -130,10 +130,10 @@ generate_status_desc(enum svn_wc_status_
    RELATIVE_TO_PATH and TARGET_PATH must be based on the same parent path,
    i.e. they can either both be absolute or they can both be relative to the
    same parent directory. Both paths are expected to be canonical.
-   
+
    If above conditions are met, a relative path that leads to TARGET_ABSPATH
    from RELATIVE_TO_PATH is returned, but there is no error checking involved.
-   
+
    The returned path is allocated from RESULT_POOL, all other allocations are
    made in SCRATCH_POOL. */
 static const char *
@@ -148,7 +148,7 @@ make_relpath(const char *relative_to_pat
   /* An example:
    *  relative_to_path = /a/b/c
    *  target_path      = /a/x/y/z
-   *  result           = ../../x/y/z 
+   *  result           = ../../x/y/z
    *
    * Another example (Windows specific):
    *  relative_to_path = F:/wc
@@ -187,7 +187,7 @@ make_relpath(const char *relative_to_pat
 /* Print STATUS and PATH in a format determined by DETAILED and
    SHOW_LAST_COMMITTED. */
 static svn_error_t *
-print_status(const char *path,
+print_status(const char *cwd_abspath, const char *path,
              svn_boolean_t detailed,
              svn_boolean_t show_last_committed,
              svn_boolean_t repos_locks,
@@ -205,6 +205,8 @@ print_status(const char *path,
   const char *moved_from_line = "";
   const char *moved_to_line = "";
 
+  path = make_relpath(cwd_abspath, path, pool, pool);
+
   /* For historic reasons svn ignores the property status for added nodes, even
      if these nodes were copied and have local property changes.
 
@@ -277,13 +279,12 @@ print_status(const char *path,
    * move info for in 'svn status'. See also comments in svn_wc_status3_t. */
   if (status->moved_from_abspath || status->moved_to_abspath)
     {
-      const char *cwd;
       const char *relpath;
-      SVN_ERR(svn_dirent_get_absolute(&cwd, "", pool));
 
       if (status->moved_from_abspath)
         {
-          relpath = make_relpath(cwd, status->moved_from_abspath, pool, pool);
+          relpath = make_relpath(cwd_abspath, status->moved_from_abspath,
+                                 pool, pool);
           relpath = svn_dirent_local_style(relpath, pool);
           moved_from_line = apr_pstrcat(pool, "\n        > ",
                                         apr_psprintf(pool, _("moved from %s"),
@@ -293,7 +294,8 @@ print_status(const char *path,
 
       if (status->moved_to_abspath)
         {
-          relpath = make_relpath(cwd, status->moved_to_abspath, pool, pool);
+          relpath = make_relpath(cwd_abspath, status->moved_to_abspath,
+                                 pool, pool);
           relpath = svn_dirent_local_style(relpath, pool);
           moved_to_line = apr_pstrcat(pool, "\n        > ",
                                       apr_psprintf(pool, _("moved to %s"),
@@ -419,7 +421,8 @@ print_status(const char *path,
 
 
 svn_error_t *
-svn_cl__print_status_xml(const char *path,
+svn_cl__print_status_xml(const char *cwd_abspath,
+                         const char *path,
                          const svn_client_status_t *status,
                          svn_client_ctx_t *ctx,
                          apr_pool_t *pool)
@@ -429,13 +432,16 @@ svn_cl__print_status_xml(const char *pat
   const char *local_abspath = status->local_abspath;
   svn_boolean_t tree_conflicted = FALSE;
 
-  if (status->node_status == svn_wc_status_none)
+  if (status->node_status == svn_wc_status_none
+      && status->repos_node_status == svn_wc_status_none)
     return SVN_NO_ERROR;
 
   if (status->conflicted)
     SVN_ERR(svn_wc_conflicted_p3(NULL, NULL, &tree_conflicted,
                                  ctx->wc_ctx, local_abspath, pool));
 
+  path = make_relpath(cwd_abspath, path, pool, pool);
+
   svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                         "path", svn_dirent_local_style(path, pool), NULL);
 
@@ -464,18 +470,19 @@ svn_cl__print_status_xml(const char *pat
                  "true");
   if (status->moved_from_abspath || status->moved_to_abspath)
     {
-      const char *cwd;
       const char *relpath;
-      SVN_ERR(svn_dirent_get_absolute(&cwd, "", pool));
+
       if (status->moved_from_abspath)
         {
-          relpath = make_relpath(cwd, status->moved_from_abspath, pool, pool);
+          relpath = make_relpath(cwd_abspath, status->moved_from_abspath,
+                                 pool, pool);
           relpath = svn_dirent_local_style(relpath, pool);
           apr_hash_set(att_hash, "moved-from", APR_HASH_KEY_STRING, relpath);
         }
       if (status->moved_to_abspath)
         {
-          relpath = make_relpath(cwd, status->moved_to_abspath, pool, pool);
+          relpath = make_relpath(cwd_abspath, status->moved_to_abspath,
+                                 pool, pool);
           relpath = svn_dirent_local_style(relpath, pool);
           apr_hash_set(att_hash, "moved-to", APR_HASH_KEY_STRING, relpath);
         }
@@ -519,8 +526,10 @@ svn_cl__print_status_xml(const char *pat
 
 /* Called by status-cmd.c */
 svn_error_t *
-svn_cl__print_status(const char *path,
+svn_cl__print_status(const char *cwd_abspath,
+                     const char *path,
                      const svn_client_status_t *status,
+                     svn_boolean_t suppress_externals_placeholders,
                      svn_boolean_t detailed,
                      svn_boolean_t show_last_committed,
                      svn_boolean_t skip_unrecognized,
@@ -540,7 +549,33 @@ svn_cl__print_status(const char *path,
           && status->repos_node_status == svn_wc_status_none))
     return SVN_NO_ERROR;
 
-  return print_status(svn_dirent_local_style(path, pool),
+  /* If we're trying not to print boring "X  /path/to/external"
+     lines..." */
+  if (suppress_externals_placeholders)
+    {
+      /* ... skip regular externals unmodified in the repository. */
+      if ((status->node_status == svn_wc_status_external)
+          && (status->repos_node_status == svn_wc_status_none)
+          && (! status->conflicted))
+        return SVN_NO_ERROR;
+
+      /* ... skip file externals that aren't modified locally or
+         remotely, changelisted, or locked (in either sense of the
+         word). */
+      if ((status->file_external)
+          && (status->repos_node_status == svn_wc_status_none)
+          && ((status->node_status == svn_wc_status_normal)
+              || (status->node_status == svn_wc_status_none))
+          && ((status->prop_status == svn_wc_status_normal)
+              || (status->prop_status == svn_wc_status_none))
+          && (! status->changelist)
+          && (! status->lock)
+          && (! status->wc_is_locked)
+          && (! status->conflicted))
+        return SVN_NO_ERROR;
+    }
+
+  return print_status(cwd_abspath, svn_dirent_local_style(path, pool),
                       detailed, show_last_committed, repos_locks, status,
                       text_conflicts, prop_conflicts, tree_conflicts,
                       ctx, pool);

Modified: subversion/branches/javahl-ra/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/util.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/util.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/util.c Mon Apr 23 12:32:48 2012
@@ -947,7 +947,7 @@ svn_cl__try(svn_error_t *err,
       va_list ap;
 
       va_start(ap, quiet);
-      while ((apr_err = va_arg(ap, apr_status_t)) != SVN_NO_ERROR)
+      while ((apr_err = va_arg(ap, apr_status_t)) != APR_SUCCESS)
         {
           if (errors_seen)
             {
@@ -1423,3 +1423,43 @@ svn_cl__local_style_skip_ancestor(const 
 
   return svn_dirent_local_style(relpath ? relpath : path, pool);
 }
+
+/* Return a string of the form "PATH_OR_URL@REVISION". */
+static const char *
+path_for_display(const char *path_or_url,
+                 const svn_opt_revision_t *revision,
+                 apr_pool_t *pool)
+{
+  const char *rev_str = svn_opt__revision_to_string(revision, pool);
+
+  if (! svn_path_is_url(path_or_url))
+    path_or_url = svn_dirent_local_style(path_or_url, pool);
+  return apr_psprintf(pool, "%s@%s", path_or_url, rev_str);
+}
+
+svn_error_t *
+svn_cl__check_related_source_and_target(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 *pool)
+{
+  const char *ancestor_url;
+  svn_revnum_t ancestor_rev;
+
+  SVN_ERR(svn_client__youngest_common_ancestor(
+            &ancestor_url, &ancestor_rev,
+            path_or_url1, revision1, path_or_url2, revision2,
+            ctx, pool, pool));
+
+  if (ancestor_url == NULL)
+    {
+      return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                               _("Source and target have no common ancestor: "
+                                 "'%s' and '%s'"),
+                               path_for_display(path_or_url1, revision1, pool),
+                               path_for_display(path_or_url2, revision2, pool));
+    }
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/javahl-ra/subversion/svnadmin/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnadmin/main.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnadmin/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svnadmin/main.c Mon Apr 23 12:32:48 2012
@@ -40,6 +40,7 @@
 #include "svn_props.h"
 #include "svn_time.h"
 #include "svn_user.h"
+#include "svn_xml.h"
 
 #include "private/svn_opt_private.h"
 
@@ -107,12 +108,14 @@ open_repos(svn_repos_t **repos,
            const char *path,
            apr_pool_t *pool)
 {
-  /* construct FS configuration parameters: enable all available caches */
+  /* construct FS configuration parameters: enable caches for r/o data */
   apr_hash_t *fs_config = apr_hash_make(pool);
   apr_hash_set(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
                APR_HASH_KEY_STRING, "1");
   apr_hash_set(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                APR_HASH_KEY_STRING, "1");
+  apr_hash_set(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+               APR_HASH_KEY_STRING, "0");
 
   /* now, open the requested repository */
   SVN_ERR(svn_repos_open2(repos, path, fs_config, pool));
@@ -152,6 +155,7 @@ static svn_opt_subcommand_t
   subcommand_load,
   subcommand_list_dblogs,
   subcommand_list_unused_dblogs,
+  subcommand_lock,
   subcommand_lslocks,
   subcommand_lstxns,
   subcommand_pack,
@@ -161,6 +165,7 @@ static svn_opt_subcommand_t
   subcommand_setlog,
   subcommand_setrevprop,
   subcommand_setuuid,
+  subcommand_unlock,
   subcommand_upgrade,
   subcommand_verify;
 
@@ -208,7 +213,7 @@ static const apr_getopt_option_t options
      N_("specify revision number ARG (or X:Y range)")},
 
     {"incremental",   svnadmin__incremental, 0,
-     N_("dump incrementally")},
+     N_("dump or hotcopy incrementally")},
 
     {"deltas",        svnadmin__deltas, 0,
      N_("use deltas in dump output")},
@@ -332,8 +337,10 @@ static const svn_opt_subcommand_desc2_t 
 
   {"hotcopy", subcommand_hotcopy, {0}, N_
    ("usage: svnadmin hotcopy REPOS_PATH NEW_REPOS_PATH\n\n"
-    "Makes a hot copy of a repository.\n"),
-   {svnadmin__clean_logs} },
+    "Makes a hot copy of a repository.\n"
+    "If --incremental is passed, data which already exists at the destination\n"
+    "is not copied again.  Incremental mode is implemented for FSFS repositories.\n"),
+   {svnadmin__clean_logs, svnadmin__incremental} },
 
   {"list-dblogs", subcommand_list_dblogs, {0}, N_
    ("usage: svnadmin list-dblogs REPOS_PATH\n\n"
@@ -359,6 +366,13 @@ static const svn_opt_subcommand_desc2_t 
     svnadmin__use_pre_commit_hook, svnadmin__use_post_commit_hook,
     svnadmin__parent_dir, svnadmin__bypass_prop_validation, 'M'} },
 
+  {"lock", subcommand_lock, {0}, N_
+   ("usage: svnadmin lock REPOS_PATH PATH USERNAME COMMENT-FILE [TOKEN]\n\n"
+    "Lock PATH by USERNAME setting comments from COMMENT-FILE.\n"
+    "If provided, use TOKEN as lock token.  Use --bypass-hooks to avoid\n"
+    "triggering the pre-lock and post-lock hook scripts.\n"),
+  {svnadmin__bypass_hooks} },
+
   {"lslocks", subcommand_lslocks, {0}, N_
    ("usage: svnadmin lslocks REPOS_PATH [PATH-IN-REPOS]\n\n"
     "Print descriptions of all locks on or under PATH-IN-REPOS (which,\n"
@@ -424,6 +438,13 @@ static const svn_opt_subcommand_desc2_t 
     "generate a brand new UUID for the repository.\n"),
    {0} },
 
+  {"unlock", subcommand_unlock, {0}, N_
+   ("usage: svnadmin unlock REPOS_PATH LOCKED_PATH USERNAME TOKEN\n\n"
+    "Unlocked LOCKED_PATH (as USERNAME) after verifying that the token\n"
+    "associated with the lock matches TOKEN.  Use --bypass-hooks to avoid\n"
+    "triggering the pre-unlock and post-unlock hook scripts.\n"),
+   {svnadmin__bypass_hooks} },
+
   {"upgrade", subcommand_upgrade, {0}, N_
    ("usage: svnadmin upgrade REPOS_PATH\n\n"
     "Upgrade the repository located at REPOS_PATH to the latest supported\n"
@@ -1008,7 +1029,7 @@ subcommand_load(apr_getopt_t *os, void *
     {
       lower = upper;
     }
-  
+
   /* Ensure correct range ordering. */
   if (lower > upper)
     {
@@ -1431,10 +1452,74 @@ subcommand_hotcopy(apr_getopt_t *os, voi
   new_repos_path = APR_ARRAY_IDX(targets, 0, const char *);
   SVN_ERR(target_arg_to_dirent(&new_repos_path, new_repos_path, pool));
 
-  return svn_repos_hotcopy(opt_state->repository_path, new_repos_path,
-                           opt_state->clean_logs, pool);
+  return svn_repos_hotcopy2(opt_state->repository_path, new_repos_path,
+                            opt_state->clean_logs, opt_state->incremental,
+                            check_cancel, NULL, pool);
 }
 
+/* This implements `svn_opt_subcommand_t'. */
+static svn_error_t *
+subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+  struct svnadmin_opt_state *opt_state = baton;
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_fs_access_t *access;
+  apr_array_header_t *args;
+  const char *username;
+  const char *lock_path;
+  const char *comment_file_name;
+  svn_stringbuf_t *file_contents;
+  const char *lock_path_utf8;
+  svn_lock_t *lock;
+  const char *lock_token = NULL;
+
+  /* Expect three more arguments: PATH USERNAME COMMENT-FILE */
+  SVN_ERR(parse_args(&args, os, 3, 4, pool));
+  lock_path = APR_ARRAY_IDX(args, 0, const char *);
+  username = APR_ARRAY_IDX(args, 1, const char *);
+  comment_file_name = APR_ARRAY_IDX(args, 2, const char *);
+
+  /* Expect one more optional argument: TOKEN */
+  if (args->nelts == 4)
+    lock_token = APR_ARRAY_IDX(args, 3, const char *);
+
+  SVN_ERR(target_arg_to_dirent(&comment_file_name, comment_file_name, pool));
+
+  SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
+  fs = svn_repos_fs(repos);
+
+  /* Create an access context describing the user. */
+  SVN_ERR(svn_fs_create_access(&access, username, pool));
+
+  /* Attach the access context to the filesystem. */
+  SVN_ERR(svn_fs_set_access(fs, access));
+
+  SVN_ERR(svn_stringbuf_from_file2(&file_contents, comment_file_name, pool));
+
+  SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, pool));
+
+  if (opt_state->bypass_hooks)
+    SVN_ERR(svn_fs_lock(&lock, fs, lock_path_utf8,
+                        lock_token,
+                        file_contents->data, /* comment */
+                        0,                   /* is_dav_comment */
+                        0,                   /* no expiration time. */
+                        SVN_INVALID_REVNUM,
+                        FALSE, pool));
+  else
+    SVN_ERR(svn_repos_fs_lock(&lock, repos, lock_path_utf8,
+                              lock_token,
+                              file_contents->data, /* comment */
+                              0,                   /* is_dav_comment */
+                              0,                   /* no expiration time. */
+                              SVN_INVALID_REVNUM,
+                              FALSE, pool));
+
+  SVN_ERR(svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"),
+                             lock_path, username));
+  return SVN_NO_ERROR;
+}
 
 static svn_error_t *
 subcommand_lslocks(apr_getopt_t *os, void *baton, apr_pool_t *pool)
@@ -1579,6 +1664,47 @@ subcommand_rmlocks(apr_getopt_t *os, voi
 
 /* This implements `svn_opt_subcommand_t'. */
 static svn_error_t *
+subcommand_unlock(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+  struct svnadmin_opt_state *opt_state = baton;
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_fs_access_t *access;
+  apr_array_header_t *args;
+  const char *username;
+  const char *lock_path;
+  const char *lock_path_utf8;
+  const char *lock_token = NULL;
+
+  /* Expect three more arguments: PATH USERNAME TOKEN */
+  SVN_ERR(parse_args(&args, os, 3, 3, pool));
+  lock_path = APR_ARRAY_IDX(args, 0, const char *);
+  username = APR_ARRAY_IDX(args, 1, const char *);
+  lock_token = APR_ARRAY_IDX(args, 2, const char *);
+
+  /* Open the repos/FS, and associate an access context containing
+     USERNAME. */
+  SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
+  fs = svn_repos_fs(repos);
+  SVN_ERR(svn_fs_create_access(&access, username, pool));
+  SVN_ERR(svn_fs_set_access(fs, access));
+
+  SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, pool));
+  if (opt_state->bypass_hooks)
+    SVN_ERR(svn_fs_unlock(fs, lock_path_utf8, lock_token,
+                          FALSE, pool));
+  else
+    SVN_ERR(svn_repos_fs_unlock(repos, lock_path_utf8, lock_token,
+                                FALSE, pool));
+
+  SVN_ERR(svn_cmdline_printf(pool, _("'%s' unlocked by user '%s'.\n"),
+                             lock_path, username));
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements `svn_opt_subcommand_t'. */
+static svn_error_t *
 subcommand_upgrade(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 {
   svn_error_t *err;
@@ -1644,7 +1770,6 @@ main(int argc, const char *argv[])
 {
   svn_error_t *err;
   apr_status_t apr_err;
-  apr_allocator_t *allocator;
   apr_pool_t *pool;
 
   const svn_opt_subcommand_desc2_t *subcommand = NULL;
@@ -1661,13 +1786,7 @@ main(int argc, const char *argv[])
   /* Create our top-level pool.  Use a separate mutexless allocator,
    * given this application is single threaded.
    */
-  if (apr_allocator_create(&allocator))
-    return EXIT_FAILURE;
-
-  apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
-
-  pool = svn_pool_create_ex(NULL, allocator);
-  apr_allocator_owner_set(allocator, pool);
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
   received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
 

Modified: subversion/branches/javahl-ra/subversion/svndumpfilter/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svndumpfilter/main.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svndumpfilter/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svndumpfilter/main.c Mon Apr 23 12:32:48 2012
@@ -79,7 +79,7 @@ create_stdio_stream(svn_stream_t **strea
 
 /* Writes a property in dumpfile format to given stringbuf. */
 static void
-write_prop_to_stringbuf(svn_stringbuf_t **strbuf,
+write_prop_to_stringbuf(svn_stringbuf_t *strbuf,
                         const char *name,
                         const svn_string_t *value)
 {
@@ -89,28 +89,31 @@ write_prop_to_stringbuf(svn_stringbuf_t 
 
   /* Output name length, then name. */
   namelen = strlen(name);
-  svn_stringbuf_appendbytes(*strbuf, "K ", 2);
+  svn_stringbuf_appendbytes(strbuf, "K ", 2);
 
   bytes_used = apr_snprintf(buf, sizeof(buf), "%" APR_SIZE_T_FMT, namelen);
-  svn_stringbuf_appendbytes(*strbuf, buf, bytes_used);
-  svn_stringbuf_appendbyte(*strbuf, '\n');
+  svn_stringbuf_appendbytes(strbuf, buf, bytes_used);
+  svn_stringbuf_appendbyte(strbuf, '\n');
 
-  svn_stringbuf_appendbytes(*strbuf, name, namelen);
-  svn_stringbuf_appendbyte(*strbuf, '\n');
+  svn_stringbuf_appendbytes(strbuf, name, namelen);
+  svn_stringbuf_appendbyte(strbuf, '\n');
 
   /* Output value length, then value. */
-  svn_stringbuf_appendbytes(*strbuf, "V ", 2);
+  svn_stringbuf_appendbytes(strbuf, "V ", 2);
 
   bytes_used = apr_snprintf(buf, sizeof(buf), "%" APR_SIZE_T_FMT, value->len);
-  svn_stringbuf_appendbytes(*strbuf, buf, bytes_used);
-  svn_stringbuf_appendbyte(*strbuf, '\n');
+  svn_stringbuf_appendbytes(strbuf, buf, bytes_used);
+  svn_stringbuf_appendbyte(strbuf, '\n');
 
-  svn_stringbuf_appendbytes(*strbuf, value->data, value->len);
-  svn_stringbuf_appendbyte(*strbuf, '\n');
+  svn_stringbuf_appendbytes(strbuf, value->data, value->len);
+  svn_stringbuf_appendbyte(strbuf, '\n');
 }
 
 
-/* Prefix matching function to compare node-path with set of prefixes. */
+/* Compare the node-path PATH with the (const char *) prefixes in PFXLIST.
+ * Return TRUE if any prefix is a prefix of PATH (matching whole path
+ * components); FALSE otherwise.
+ * PATH starts with a '/', as do the (const char *) paths in PREFIXES. */
 static svn_boolean_t
 ary_prefix_match(const apr_array_header_t *pfxlist, const char *path)
 {
@@ -125,7 +128,7 @@ ary_prefix_match(const apr_array_header_
       if (path_len < pfx_len)
         continue;
       if (strncmp(path, pfx, pfx_len) == 0
-          && (path[pfx_len] == '\0' || path[pfx_len] == '/'))
+          && (pfx_len == 1 || path[pfx_len] == '\0' || path[pfx_len] == '/'))
         return TRUE;
     }
 
@@ -134,7 +137,8 @@ ary_prefix_match(const apr_array_header_
 
 
 /* Check whether we need to skip this PATH based on its presence in
-   the PREFIXES list, and the DO_EXCLUDE option. */
+   the PREFIXES list, and the DO_EXCLUDE option.
+   PATH starts with a '/', as do the (const char *) paths in PREFIXES. */
 static APR_INLINE svn_boolean_t
 skip_path(const char *path, const apr_array_header_t *prefixes,
           svn_boolean_t do_exclude, svn_boolean_t glob)
@@ -360,7 +364,7 @@ output_revision(struct revision_baton_t 
           const char *pname = svn__apr_hash_index_key(hi);
           const svn_string_t *pval = svn__apr_hash_index_val(hi);
 
-          write_prop_to_stringbuf(&props, pname, pval);
+          write_prop_to_stringbuf(props, pname, pval);
         }
       svn_stringbuf_appendcstr(props, "PROPS-END\n");
       svn_stringbuf_appendcstr(rb->header,
@@ -800,7 +804,7 @@ set_node_property(void *node_baton,
       value = filtered_mergeinfo;
     }
 
-  write_prop_to_stringbuf(&(nb->props), name, value);
+  write_prop_to_stringbuf(nb->props, name, value);
 
   return SVN_NO_ERROR;
 }
@@ -1258,7 +1262,6 @@ main(int argc, const char *argv[])
 {
   svn_error_t *err;
   apr_status_t apr_err;
-  apr_allocator_t *allocator;
   apr_pool_t *pool;
 
   const svn_opt_subcommand_desc2_t *subcommand = NULL;
@@ -1276,13 +1279,7 @@ main(int argc, const char *argv[])
   /* Create our top-level pool.  Use a separate mutexless allocator,
    * given this application is single threaded.
    */
-  if (apr_allocator_create(&allocator))
-   return EXIT_FAILURE;
-
-  apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
-
-  pool = svn_pool_create_ex(NULL, allocator);
-  apr_allocator_owner_set(allocator, pool);
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
   /* Check library versions */
   err = check_lib_versions();

Modified: subversion/branches/javahl-ra/subversion/svnlook/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnlook/main.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnlook/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svnlook/main.c Mon Apr 23 12:32:48 2012
@@ -445,7 +445,6 @@ generate_delta_tree(svn_repos_node_t **t
                     svn_repos_t *repos,
                     svn_fs_root_t *root,
                     svn_revnum_t base_rev,
-                    svn_boolean_t use_copy_history,
                     apr_pool_t *pool)
 {
   svn_fs_root_t *base_root;
@@ -462,7 +461,7 @@ generate_delta_tree(svn_repos_node_t **t
                                 base_root, root, pool, edit_pool));
 
   /* Drive our editor. */
-  SVN_ERR(svn_repos_replay2(root, "", SVN_INVALID_REVNUM, FALSE,
+  SVN_ERR(svn_repos_replay2(root, "", SVN_INVALID_REVNUM, TRUE,
                             editor, edit_baton, NULL, NULL, edit_pool));
 
   /* Return the tree we just built. */
@@ -784,18 +783,25 @@ generate_label(const char **label,
    If TOKEN is empty, or is already terminated by an EOL marker,
    return TOKEN unmodified. Else, return a new string consisting
    of the concatenation of TOKEN and the system's default EOL marker.
-   The new string is allocated from POOL. */
+   The new string is allocated from POOL.
+   If HAD_EOL is not NULL, indicate in *HAD_EOL if the token had a EOL. */
 static const svn_string_t *
-maybe_append_eol(const svn_string_t *token, apr_pool_t *pool)
+maybe_append_eol(const svn_string_t *token, svn_boolean_t *had_eol,
+                 apr_pool_t *pool)
 {
   const char *curp;
 
+  if (had_eol)
+    *had_eol = FALSE;
+
   if (token->len == 0)
     return token;
 
   curp = token->data + token->len - 1;
   if (*curp == '\r')
     {
+      if (had_eol)
+        *had_eol = TRUE;
       return token;
     }
   else if (*curp != '\n')
@@ -804,6 +810,8 @@ maybe_append_eol(const svn_string_t *tok
     }
   else
     {
+      if (had_eol)
+        *had_eol = TRUE;
       return token;
     }
 }
@@ -860,19 +868,20 @@ display_prop_diffs(const apr_array_heade
         const svn_string_t *tmp;
         const svn_string_t *orig;
         const svn_string_t *val;
+        svn_boolean_t val_has_eol;
 
         SVN_ERR(svn_stream_for_stdout(&out, pool));
 
         /* The last character in a property is often not a newline.
-           Since the diff is not useful anyway for patching properties an
-           eol character is appended when needed to remove those pescious
-           ' \ No newline at end of file' lines. */
+           An eol character is appended to prevent the diff API to add a
+           ' \ No newline at end of file' line. We add
+           ' \ No newline at end of property' manually if needed. */
         tmp = orig_value ? orig_value : svn_string_create_empty(pool);
-        orig = maybe_append_eol(tmp, pool);
+        orig = maybe_append_eol(tmp, NULL, pool);
 
         tmp = pc->value ? pc->value :
                                   svn_string_create_empty(pool);
-        val = maybe_append_eol(tmp, pool);
+        val = maybe_append_eol(tmp, &val_has_eol, pool);
 
         SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, pool));
 
@@ -888,6 +897,12 @@ display_prop_diffs(const apr_array_heade
                                            svn_dirent_local_style(path, pool),
                                            svn_cmdline_output_encoding(pool),
                                            orig, val, pool));
+        if (!val_has_eol)
+          {
+            const char *s = "\\ No newline at end of property" APR_EOL_STR;
+            apr_size_t len = strlen(s);
+            SVN_ERR(svn_stream_write(out, s, &len));
+          }
       }
     }
   return svn_cmdline_fflush(stdout);
@@ -1385,8 +1400,7 @@ do_dirs_changed(svnlook_ctxt_t *c, apr_p
        _("Transaction '%s' is not based on a revision; how odd"),
        c->txn_name);
 
-  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id,
-                              TRUE, pool));
+  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id, pool));
   if (tree)
     SVN_ERR(print_dirs_changed_tree(tree, "", pool));
 
@@ -1491,8 +1505,7 @@ do_changed(svnlook_ctxt_t *c, apr_pool_t
        _("Transaction '%s' is not based on a revision; how odd"),
        c->txn_name);
 
-  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id,
-                              TRUE, pool));
+  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id, pool));
   if (tree)
     SVN_ERR(print_changed_tree(tree, "", c->copy_info, pool));
 
@@ -1520,8 +1533,7 @@ do_diff(svnlook_ctxt_t *c, apr_pool_t *p
        _("Transaction '%s' is not based on a revision; how odd"),
        c->txn_name);
 
-  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id,
-                              TRUE, pool));
+  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id, pool));
   if (tree)
     {
       const char *tmpdir;
@@ -2239,7 +2251,6 @@ main(int argc, const char *argv[])
 {
   svn_error_t *err;
   apr_status_t apr_err;
-  apr_allocator_t *allocator;
   apr_pool_t *pool;
 
   const svn_opt_subcommand_desc2_t *subcommand = NULL;
@@ -2256,13 +2267,7 @@ main(int argc, const char *argv[])
   /* Create our top-level pool.  Use a separate mutexless allocator,
    * given this application is single threaded.
    */
-  if (apr_allocator_create(&allocator))
-    return EXIT_FAILURE;
-
-  apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
-
-  pool = svn_pool_create_ex(NULL, allocator);
-  apr_allocator_owner_set(allocator, pool);
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
   received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
 

Modified: subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c Mon Apr 23 12:32:48 2012
@@ -81,6 +81,9 @@ struct dump_edit_baton {
   /* The output stream we write the dumpfile to */
   svn_stream_t *stream;
 
+  /* A backdoor ra session to fetch additional information during the edit. */
+  svn_ra_session_t *ra_session;
+
   /* Pool for per-revision allocations */
   apr_pool_t *pool;
 
@@ -109,6 +112,9 @@ struct dump_edit_baton {
   svn_boolean_t dump_text;
   svn_boolean_t dump_props;
   svn_boolean_t dump_newlines;
+
+  /* The revision we're currently dumping. */
+  svn_revnum_t current_revision;
 };
 
 /* Make a directory baton to represent the directory at PATH (relative
@@ -163,58 +169,90 @@ make_dir_baton(const char *path,
   return new_db;
 }
 
+/* Return in *HEADER and *CONTENT the headers and content for PROPS. */
+static svn_error_t *
+get_props_content(svn_stringbuf_t **header,
+                  svn_stringbuf_t **content,
+                  apr_hash_t *props,
+                  apr_hash_t *deleted_props,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  svn_stream_t *content_stream;
+  apr_hash_t *normal_props;
+  const char *buf;
+
+  *content = svn_stringbuf_create_empty(result_pool);
+  *header = svn_stringbuf_create_empty(result_pool);
+
+  content_stream = svn_stream_from_stringbuf(*content, scratch_pool);
+
+  SVN_ERR(svn_rdump__normalize_props(&normal_props, props, scratch_pool));
+  SVN_ERR(svn_hash_write_incremental(normal_props, deleted_props,
+                                     content_stream, "PROPS-END",
+                                     scratch_pool));
+  SVN_ERR(svn_stream_close(content_stream));
+
+  /* Prop-delta: true */
+  *header = svn_stringbuf_createf(result_pool, SVN_REPOS_DUMPFILE_PROP_DELTA
+                                  ": true\n");
+
+  /* Prop-content-length: 193 */
+  buf = apr_psprintf(scratch_pool, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
+                     ": %" APR_SIZE_T_FMT "\n", (*content)->len);
+  svn_stringbuf_appendcstr(*header, buf);
+
+  return SVN_NO_ERROR;
+}
+
 /* Extract and dump properties stored in edit baton EB, using POOL for
  * any temporary allocations. If TRIGGER_VAR is not NULL, it is set to FALSE.
  * Unless DUMP_DATA_TOO is set, only property headers are dumped.
  */
 static svn_error_t *
-do_dump_props(struct dump_edit_baton *eb,
+do_dump_props(svn_stringbuf_t **propstring,
+              svn_stream_t *stream,
+              apr_hash_t *props,
+              apr_hash_t *deleted_props,
               svn_boolean_t *trigger_var,
               svn_boolean_t dump_data_too,
-              apr_pool_t *pool)
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
 {
-  svn_stream_t *propstream;
-  apr_hash_t *normal_props;
+  svn_stringbuf_t *header;
+  svn_stringbuf_t *content;
+  apr_size_t len;
 
   if (trigger_var && !*trigger_var)
     return SVN_NO_ERROR;
 
-  SVN_ERR(svn_rdump__normalize_props(&normal_props, eb->props, eb->pool));
-  svn_stringbuf_setempty(eb->propstring);
-  propstream = svn_stream_from_stringbuf(eb->propstring, eb->pool);
-  SVN_ERR(svn_hash_write_incremental(normal_props, eb->deleted_props,
-                                     propstream, "PROPS-END", pool));
-  SVN_ERR(svn_stream_close(propstream));
+  SVN_ERR(get_props_content(&header, &content, props, deleted_props,
+                            result_pool, scratch_pool));
 
-  /* Prop-delta: true */
-  SVN_ERR(svn_stream_printf(eb->stream, pool,
-                            SVN_REPOS_DUMPFILE_PROP_DELTA
-                            ": true\n"));
+  /* This is a wacky side-effect of this function. */
+  *propstring = content;
 
-  /* Prop-content-length: 193 */
-  SVN_ERR(svn_stream_printf(eb->stream, pool,
-                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n", eb->propstring->len));
+  len = header->len;
+  SVN_ERR(svn_stream_write(stream, header->data, &len));
 
   if (dump_data_too)
     {
       /* Content-length: 14 */
-      SVN_ERR(svn_stream_printf(eb->stream, pool,
+      SVN_ERR(svn_stream_printf(stream, scratch_pool,
                                 SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                                 ": %" APR_SIZE_T_FMT "\n\n",
-                                eb->propstring->len));
+                                content->len));
 
-      /* The properties. */
-      SVN_ERR(svn_stream_write(eb->stream, eb->propstring->data,
-                               &(eb->propstring->len)));
+      len = content->len;
+      SVN_ERR(svn_stream_write(stream, content->data, &len));
 
       /* No text is going to be dumped. Write a couple of newlines and
          wait for the next node/ revision. */
-      SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+      SVN_ERR(svn_stream_printf(stream, scratch_pool, "\n\n"));
 
       /* Cleanup so that data is never dumped twice. */
-      SVN_ERR(svn_hash__clear(eb->props, eb->pool));
-      SVN_ERR(svn_hash__clear(eb->deleted_props, eb->pool));
+      SVN_ERR(svn_hash__clear(props, scratch_pool));
+      SVN_ERR(svn_hash__clear(deleted_props, scratch_pool));
       if (trigger_var)
         *trigger_var = FALSE;
     }
@@ -403,7 +441,9 @@ delete_entry(const char *path,
   LDR_DBG(("delete_entry %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(do_dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+  SVN_ERR(do_dump_props(&pb->eb->propstring, pb->eb->stream,
+                        pb->eb->props, pb->eb->deleted_props,
+                        &(pb->eb->dump_props), TRUE, pool, pool));
 
   /* Some pending newlines to dump? */
   SVN_ERR(do_dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
@@ -435,7 +475,9 @@ add_directory(const char *path,
                           pb, TRUE, pb->eb->pool);
 
   /* Some pending properties to dump? */
-  SVN_ERR(do_dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+  SVN_ERR(do_dump_props(&pb->eb->propstring, pb->eb->stream,
+                        pb->eb->props, pb->eb->deleted_props,
+                        &(pb->eb->dump_props), TRUE, pool, pool));
 
   /* Some pending newlines to dump? */
   SVN_ERR(do_dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
@@ -480,7 +522,9 @@ open_directory(const char *path,
   LDR_DBG(("open_directory %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(do_dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+  SVN_ERR(do_dump_props(&pb->eb->propstring, pb->eb->stream,
+                        pb->eb->props, pb->eb->deleted_props,
+                        &(pb->eb->dump_props), TRUE, pool, pool));
 
   /* Some pending newlines to dump? */
   SVN_ERR(do_dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
@@ -512,7 +556,9 @@ close_directory(void *dir_baton,
   LDR_DBG(("close_directory %p\n", dir_baton));
 
   /* Some pending properties to dump? */
-  SVN_ERR(do_dump_props(eb, &(eb->dump_props), TRUE, pool));
+  SVN_ERR(do_dump_props(&eb->propstring, eb->stream,
+                        eb->props, eb->deleted_props,
+                        &(eb->dump_props), TRUE, pool, pool));
 
   /* Some pending newlines to dump? */
   SVN_ERR(do_dump_newlines(eb, &(eb->dump_newlines), pool));
@@ -546,7 +592,9 @@ add_file(const char *path,
   LDR_DBG(("add_file %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(do_dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+  SVN_ERR(do_dump_props(&pb->eb->propstring, pb->eb->stream,
+                        pb->eb->props, pb->eb->deleted_props,
+                        &(pb->eb->dump_props), TRUE, pool, pool));
 
   /* Some pending newlines to dump? */
   SVN_ERR(do_dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
@@ -591,7 +639,9 @@ open_file(const char *path,
   LDR_DBG(("open_file %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(do_dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+  SVN_ERR(do_dump_props(&pb->eb->propstring, pb->eb->stream,
+                        pb->eb->props, pb->eb->deleted_props,
+                        &(pb->eb->dump_props), TRUE, pool, pool));
 
   /* Some pending newlines to dump? */
   SVN_ERR(do_dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
@@ -626,7 +676,7 @@ change_dir_prop(void *parent_baton,
 
   LDR_DBG(("change_dir_prop %p\n", parent_baton));
 
-  if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
+  if (svn_property_kind2(name) != svn_prop_regular_kind)
     return SVN_NO_ERROR;
 
   if (value)
@@ -668,7 +718,7 @@ change_file_prop(void *file_baton,
 
   LDR_DBG(("change_file_prop %p\n", file_baton));
 
-  if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
+  if (svn_property_kind2(name) != svn_prop_regular_kind)
     return SVN_NO_ERROR;
 
   if (value)
@@ -751,7 +801,9 @@ close_file(void *file_baton,
 
   /* Some pending properties to dump? Dump just the headers- dump the
      props only after dumping the text headers too (if present) */
-  SVN_ERR(do_dump_props(eb, &(eb->dump_props), FALSE, pool));
+  SVN_ERR(do_dump_props(&eb->propstring, eb->stream,
+                        eb->props, eb->deleted_props,
+                        &(eb->dump_props), FALSE, pool, pool));
 
   /* Dump the text headers */
   if (eb->dump_text)
@@ -846,10 +898,120 @@ close_edit(void *edit_baton, apr_pool_t 
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+fetch_base_func(const char **filename,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  struct dump_edit_baton *eb = baton;
+  svn_stream_t *fstream;
+  svn_error_t *err;
+
+  if (path[0] == '/')
+    path += 1;
+
+  if (! SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->current_revision - 1;
+
+  SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 result_pool, scratch_pool));
+
+  err = svn_ra_get_file(eb->ra_session, path, base_revision,
+                        fstream, NULL, NULL, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      SVN_ERR(svn_stream_close(fstream));
+
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+  else if (err)
+    return svn_error_trace(err);
+
+  SVN_ERR(svn_stream_close(fstream));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  struct dump_edit_baton *eb = baton;
+  svn_node_kind_t node_kind;
+
+  if (path[0] == '/')
+    path += 1;
+
+  if (! SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->current_revision - 1;
+
+  SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
+                            scratch_pool));
+
+  if (node_kind == svn_node_file)
+    {
+      SVN_ERR(svn_ra_get_file(eb->ra_session, path, base_revision,
+                              NULL, NULL, props, result_pool));
+    }
+  else if (node_kind == svn_node_dir)
+    {
+      apr_array_header_t *tmp_props;
+
+      SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path,
+                              base_revision, 0 /* Dirent fields */,
+                              result_pool));
+      tmp_props = svn_prop_hash_to_array(*props, result_pool);
+      SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props,
+                                   result_pool));
+      *props = svn_prop_array_to_hash(tmp_props, result_pool);
+    }
+  else
+    {
+      *props = apr_hash_make(result_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *scratch_pool)
+{
+  struct dump_edit_baton *eb = baton;
+  svn_node_kind_t node_kind;
+
+  if (path[0] == '/')
+    path += 1;
+
+  if (! SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->current_revision - 1;
+
+  SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
+                            scratch_pool));
+
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_rdump__get_dump_editor(const svn_delta_editor_t **editor,
                            void **edit_baton,
+                           svn_revnum_t revision,
                            svn_stream_t *stream,
+                           svn_ra_session_t *ra_session,
                            svn_cancel_func_t cancel_func,
                            void *cancel_baton,
                            apr_pool_t *pool)
@@ -861,6 +1023,8 @@ svn_rdump__get_dump_editor(const svn_del
 
   eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton));
   eb->stream = stream;
+  eb->ra_session = ra_session;
+  eb->current_revision = revision;
 
   /* Create a special per-revision pool */
   eb->pool = svn_pool_create(pool);
@@ -893,8 +1057,13 @@ svn_rdump__get_dump_editor(const svn_del
   SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
                                             de, eb, editor, edit_baton, pool));
 
+  shim_callbacks->fetch_base_func = fetch_base_func;
+  shim_callbacks->fetch_props_func = fetch_props_func;
+  shim_callbacks->fetch_kind_func = fetch_kind_func;
+  shim_callbacks->fetch_baton = eb;
+
   SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
-                                   shim_callbacks, pool, pool));
+                                   NULL, NULL, shim_callbacks, pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c Mon Apr 23 12:32:48 2012
@@ -384,6 +384,121 @@ lock_retry_func(void *baton,
                             reposlocktoken->data);
 }
 
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  struct revision_baton *rb = baton;
+  svn_stream_t *fstream;
+  svn_error_t *err;
+
+  if (! SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = rb->rev - 1;
+
+  SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 result_pool, scratch_pool));
+
+  err = svn_ra_get_file(rb->pb->aux_session, path, base_revision,
+                        fstream, NULL, NULL, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      SVN_ERR(svn_stream_close(fstream));
+
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+  else if (err)
+    return svn_error_trace(err);
+
+  SVN_ERR(svn_stream_close(fstream));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  struct revision_baton *rb = baton;
+  svn_node_kind_t node_kind;
+
+  if (! SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = rb->rev - 1;
+
+  SVN_ERR(svn_ra_check_path(rb->pb->aux_session, path, base_revision,
+                            &node_kind, scratch_pool));
+
+  if (node_kind == svn_node_file)
+    {
+      SVN_ERR(svn_ra_get_file(rb->pb->aux_session, path, base_revision,
+                              NULL, NULL, props, result_pool));
+    }
+  else if (node_kind == svn_node_dir)
+    {
+      apr_array_header_t *tmp_props;
+
+      SVN_ERR(svn_ra_get_dir2(rb->pb->aux_session, NULL, NULL, props, path,
+                              base_revision, 0 /* Dirent fields */,
+                              result_pool));
+      tmp_props = svn_prop_hash_to_array(*props, result_pool);
+      SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props,
+                                   result_pool));
+      *props = svn_prop_array_to_hash(tmp_props, result_pool);
+    }
+  else
+    {
+      *props = apr_hash_make(result_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *scratch_pool)
+{
+  struct revision_baton *rb = baton;
+  svn_node_kind_t node_kind;
+
+  if (! SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = rb->rev - 1;
+
+  SVN_ERR(svn_ra_check_path(rb->pb->aux_session, path, base_revision,
+                            &node_kind, scratch_pool));
+
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+  return SVN_NO_ERROR;
+}
+
+static svn_delta_shim_callbacks_t *
+get_shim_callbacks(struct revision_baton *rb,
+                   apr_pool_t *pool)
+{
+  svn_delta_shim_callbacks_t *callbacks =
+                        svn_delta_shim_callbacks_default(pool);
+
+  callbacks->fetch_props_func = fetch_props_func;
+  callbacks->fetch_kind_func = fetch_kind_func;
+  callbacks->fetch_base_func = fetch_base_func;
+  callbacks->fetch_baton = rb;
+
+  return callbacks;
+}
+
 /* Acquire a lock (of sorts) on the repository associated with the
  * given RA SESSION. This lock is just a revprop change attempt in a
  * time-delay loop. This function is duplicated by svnsync in main.c.
@@ -518,6 +633,8 @@ new_node_record(void **node_baton,
       apr_hash_set(rb->revprop_table, SVN_PROP_REVISION_DATE,
                    APR_HASH_KEY_STRING, NULL);
 
+      SVN_ERR(svn_ra__register_editor_shim_callbacks(rb->pb->session,
+                                    get_shim_callbacks(rb, rb->pool)));
       SVN_ERR(svn_ra_get_commit_editor3(rb->pb->session, &commit_editor,
                                         &commit_edit_baton, rb->revprop_table,
                                         commit_callback, revision_baton,
@@ -876,7 +993,7 @@ remove_node_props(void *baton)
   for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
     {
       const char *name = svn__apr_hash_index_key(hi);
-      svn_prop_kind_t kind = svn_property_kind(NULL, name);
+      svn_prop_kind_t kind = svn_property_kind2(name);
 
       if (kind == svn_prop_regular_kind)
         SVN_ERR(set_node_property(nb, name, NULL));

Modified: subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c Mon Apr 23 12:32:48 2012
@@ -151,11 +151,11 @@ static const apr_getopt_option_t svnrdum
 
 /* Baton for the RA replay session. */
 struct replay_baton {
-  /* The editor producing diffs. */
-  const svn_delta_editor_t *editor;
+  /* A backdoor ra session for fetching information. */
+  svn_ra_session_t *extra_ra_session;
 
-  /* Baton for the editor. */
-  void *edit_baton;
+  /* The output stream */
+  svn_stream_t *stdout_stream;
 
   /* Whether to be quiet. */
   svn_boolean_t quiet;
@@ -220,10 +220,9 @@ replay_revstart(svn_revnum_t revision,
   SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));
   SVN_ERR(svn_stream_close(stdout_stream));
 
-  /* Extract editor and editor_baton from the replay_baton and
-     set them so that the editor callbacks can use them. */
-  *editor = rb->editor;
-  *edit_baton = rb->edit_baton;
+  SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
+                                     rb->stdout_stream, rb->extra_ra_session,
+                                     check_cancel, NULL, pool));
 
   return SVN_NO_ERROR;
 }
@@ -240,6 +239,9 @@ replay_revend(svn_revnum_t revision,
 {
   /* No resources left to free. */
   struct replay_baton *rb = replay_baton;
+
+  SVN_ERR(editor->close_edit(edit_baton, pool));
+
   if (! rb->quiet)
     SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
                                 revision));
@@ -343,6 +345,7 @@ dump_revision_header(svn_ra_session_t *s
  */
 static svn_error_t *
 replay_revisions(svn_ra_session_t *session,
+                 svn_ra_session_t *extra_ra_session,
                  const char *url,
                  svn_revnum_t start_revision,
                  svn_revnum_t end_revision,
@@ -350,20 +353,15 @@ replay_revisions(svn_ra_session_t *sessi
                  svn_boolean_t incremental,
                  apr_pool_t *pool)
 {
-  const svn_delta_editor_t *dump_editor;
   struct replay_baton *replay_baton;
-  void *dump_baton;
   const char *uuid;
   svn_stream_t *stdout_stream;
 
   SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
 
-  SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton, stdout_stream,
-                                     check_cancel, NULL, pool));
-
   replay_baton = apr_pcalloc(pool, sizeof(*replay_baton));
-  replay_baton->editor = dump_editor;
-  replay_baton->edit_baton = dump_baton;
+  replay_baton->stdout_stream = stdout_stream;
+  replay_baton->extra_ra_session = extra_ra_session;
   replay_baton->quiet = quiet;
 
   /* Write the magic header and UUID */
@@ -401,6 +399,8 @@ replay_revisions(svn_ra_session_t *sessi
     {
       const svn_ra_reporter3_t *reporter;
       void *report_baton;
+      const svn_delta_editor_t *dump_editor;
+      void *dump_baton;
 
       /* First, we need to dump the start_revision in full.  We'll
          start with a revision record header. */
@@ -413,6 +413,10 @@ replay_revisions(svn_ra_session_t *sessi
          to the update reporter, telling it that we have nothing to
          start with.  The delta between nothing and everything-at-REV
          is, effectively, a full dump of REV. */
+      SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton,
+                                         start_revision,
+                                         stdout_stream, extra_ra_session,
+                                         check_cancel, NULL, pool));
       SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
                                 start_revision, "", svn_depth_infinity,
                                 FALSE, dump_editor, dump_baton, pool));
@@ -531,7 +535,17 @@ dump_cmd(apr_getopt_t *os,
          apr_pool_t *pool)
 {
   opt_baton_t *opt_baton = baton;
-  return replay_revisions(opt_baton->session, opt_baton->url,
+  svn_ra_session_t *extra_ra_session;
+  const char *repos_root;
+
+  SVN_ERR(svn_client_open_ra_session(&extra_ra_session,
+                                     opt_baton->url,
+                                     opt_baton->ctx, pool));
+  SVN_ERR(svn_ra_get_repos_root2(extra_ra_session, &repos_root, pool));
+  SVN_ERR(svn_ra_reparent(extra_ra_session, repos_root, pool));
+
+  return replay_revisions(opt_baton->session, extra_ra_session,
+                          opt_baton->url,
                           opt_baton->start_revision.value.number,
                           opt_baton->end_revision.value.number,
                           opt_baton->quiet, opt_baton->incremental, pool);
@@ -680,7 +694,6 @@ main(int argc, const char **argv)
   apr_getopt_t *os;
   const char *first_arg;
   apr_array_header_t *received_opts;
-  apr_allocator_t *allocator;
   int i;
 
   if (svn_cmdline_init ("svnrdump", stderr) != EXIT_SUCCESS)
@@ -689,13 +702,7 @@ main(int argc, const char **argv)
   /* Create our top-level pool.  Use a separate mutexless allocator,
    * given this application is single threaded.
    */
-  if (apr_allocator_create(&allocator))
-    return EXIT_FAILURE;
-
-  apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
-
-  pool = svn_pool_create_ex(NULL, allocator);
-  apr_allocator_owner_set(allocator, pool);
+  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
   opt_baton = apr_pcalloc(pool, sizeof(*opt_baton));
   opt_baton->start_revision.kind = svn_opt_revision_unspecified;

Modified: subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.h?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.h (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.h Mon Apr 23 12:32:48 2012
@@ -46,7 +46,9 @@ extern "C" {
 svn_error_t *
 svn_rdump__get_dump_editor(const svn_delta_editor_t **editor,
                            void **edit_baton,
+                           svn_revnum_t revision,
                            svn_stream_t *stream,
+                           svn_ra_session_t *ra_session,
                            svn_cancel_func_t cancel_func,
                            void *cancel_baton,
                            apr_pool_t *pool);

Modified: subversion/branches/javahl-ra/subversion/svnserve/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/main.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/main.c Mon Apr 23 12:32:48 2012
@@ -147,6 +147,8 @@ void winservice_notify_stop(void)
 #define SVNSERVE_OPT_LOG_FILE        264
 #define SVNSERVE_OPT_CACHE_TXDELTAS  265
 #define SVNSERVE_OPT_CACHE_FULLTEXTS 266
+#define SVNSERVE_OPT_CACHE_REVPROPS  267
+#define SVNSERVE_OPT_SINGLE_CONN     268
 
 static const apr_getopt_option_t svnserve__options[] =
   {
@@ -221,6 +223,14 @@ static const apr_getopt_option_t svnserv
         "Default is yes.\n"
         "                             "
         "[used for FSFS repositories only]")},
+    {"cache-revprops", SVNSERVE_OPT_CACHE_REVPROPS, 1,
+     N_("enable or disable caching of revision properties.\n"
+        "                             "
+        "Consult the documentation before activating this.\n"
+        "                             "
+        "Default is no.\n"
+        "                             "
+        "[used for FSFS repositories only]")},
 #ifdef CONNECTION_HAVE_THREAD_OPTION
     /* ### Making the assumption here that WIN32 never has fork and so
      * ### this option never exists when --service exists. */
@@ -231,6 +241,10 @@ static const apr_getopt_option_t svnserv
      N_("run in foreground (useful for debugging)\n"
         "                             "
         "[mode: daemon]")},
+    {"single-thread",    SVNSERVE_OPT_SINGLE_CONN, 0,
+     N_("handle one connection at a time in the parent process\n"
+        "                             "
+        "(useful for debugging)")},
     {"log-file",         SVNSERVE_OPT_LOG_FILE, 1,
      N_("svnserve log file")},
     {"pid-file",         SVNSERVE_OPT_PID_FILE, 1,
@@ -408,7 +422,6 @@ int main(int argc, const char *argv[])
   apr_sockaddr_t *sa;
   apr_pool_t *pool;
   apr_pool_t *connection_pool;
-  apr_allocator_t *allocator;
   svn_error_t *err;
   apr_getopt_t *os;
   int opt;
@@ -428,10 +441,13 @@ int main(int argc, const char *argv[])
   const char *host = NULL;
   int family = APR_INET;
   apr_int32_t sockaddr_info_flags = 0;
+#if APR_HAVE_IPV6
   svn_boolean_t prefer_v6 = FALSE;
+#endif
   svn_boolean_t quiet = FALSE;
   svn_boolean_t is_version = FALSE;
   int mode_opt_count = 0;
+  int handling_opt_count = 0;
   const char *config_filename = NULL;
   const char *pid_filename = NULL;
   const char *log_filename = NULL;
@@ -475,6 +491,7 @@ int main(int argc, const char *argv[])
   params.memory_cache_size = (apr_uint64_t)-1;
   params.cache_fulltexts = TRUE;
   params.cache_txdeltas = FALSE;
+  params.cache_revprops = FALSE;
 
   while (1)
     {
@@ -486,7 +503,10 @@ int main(int argc, const char *argv[])
       switch (opt)
         {
         case '6':
+#if APR_HAVE_IPV6
           prefer_v6 = TRUE;
+#endif
+          /* ### Maybe error here if we don't have IPV6 support? */
           break;
 
         case 'h':
@@ -513,6 +533,11 @@ int main(int argc, const char *argv[])
           foreground = TRUE;
           break;
 
+        case SVNSERVE_OPT_SINGLE_CONN:
+          handling_mode = connection_mode_single;
+          handling_opt_count++;
+          break;
+
         case 'i':
           if (run_mode != run_mode_inetd)
             {
@@ -585,6 +610,7 @@ int main(int argc, const char *argv[])
 
         case 'T':
           handling_mode = connection_mode_thread;
+          handling_opt_count++;
           break;
 
         case 'c':
@@ -609,6 +635,11 @@ int main(int argc, const char *argv[])
              = svn_tristate__from_word(arg) == svn_tristate_true;
           break;
 
+        case SVNSERVE_OPT_CACHE_REVPROPS:
+          params.cache_revprops
+             = svn_tristate__from_word(arg) == svn_tristate_true;
+          break;
+
 #ifdef WIN32
         case SVNSERVE_OPT_SERVICE:
           if (run_mode != run_mode_service)
@@ -665,6 +696,14 @@ int main(int argc, const char *argv[])
       usage(argv[0], pool);
     }
 
+  if (handling_opt_count > 1)
+    {
+      svn_error_clear(svn_cmdline_fputs(
+                      _("You may only specify one of -T or --single-thread\n"),
+                      stderr, pool));
+      usage(argv[0], pool);
+    }
+
   /* If a configuration file is specified, load it and any referenced
    * password and authorization files. */
   if (config_filename)
@@ -903,22 +942,12 @@ int main(int argc, const char *argv[])
         return ERROR_SUCCESS;
 #endif
 
-      /* If we are using fulltext caches etc. we will allocate many large
-         chunks of memory of various sizes outside the cache for those
-         fulltexts. Make sure we use the memory wisely: use an allocator
-         that causes memory fragments to be given back to the OS early. */
-
-      if (apr_allocator_create(&allocator))
-        return EXIT_FAILURE;
-
-      apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
-
       /* Non-standard pool handling.  The main thread never blocks to join
          the connection threads so it cannot clean up after each one.  So
          separate pools that can be cleared at thread exit are used. */
 
-      connection_pool = svn_pool_create_ex(NULL, allocator);
-      apr_allocator_owner_set(allocator, connection_pool);
+      connection_pool
+          = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
       status = apr_socket_accept(&usock, sock, connection_pool);
       if (handling_mode == connection_mode_fork)

Modified: subversion/branches/javahl-ra/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/serve.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/serve.c (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/serve.c Mon Apr 23 12:32:48 2012
@@ -243,6 +243,7 @@ svn_error_t *load_configs(svn_config_t *
   *pwdb = NULL;
   if (pwdb_path)
     {
+      pwdb_path = svn_dirent_canonicalize(pwdb_path, pool);
       pwdb_path = svn_dirent_join(base, pwdb_path, pool);
 
       err = svn_config_read2(pwdb, pwdb_path, TRUE, FALSE, pool);
@@ -290,6 +291,7 @@ svn_error_t *load_configs(svn_config_t *
     {
       const char *case_force_val;
 
+      authzdb_path = svn_dirent_canonicalize(authzdb_path, pool);
       authzdb_path = svn_dirent_join(base, authzdb_path, pool);
       err = svn_repos_authz_read(authzdb, authzdb_path, TRUE, pool);
       if (err)
@@ -1468,9 +1470,9 @@ static svn_error_t *get_dir(svn_ra_svn_c
                             apr_array_header_t *params, void *baton)
 {
   server_baton_t *b = baton;
-  const char *path, *full_path, *file_path, *cauthor, *cdate;
+  const char *path, *full_path;
   svn_revnum_t rev;
-  apr_hash_t *entries, *props = NULL, *file_props;
+  apr_hash_t *entries, *props = NULL;
   apr_hash_index_t *hi;
   svn_fs_root_t *root;
   apr_pool_t *subpool;
@@ -1538,9 +1540,17 @@ static svn_error_t *get_dir(svn_ra_svn_c
   if (want_props)
     SVN_CMD_ERR(get_props(&props, root, full_path, pool));
 
-  /* Fetch the directory entries if requested. */
+  /* Begin response ... */
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(r(!", "success", rev));
+  SVN_ERR(svn_ra_svn_write_proplist(conn, pool, props));
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(!"));
+
+  /* Fetch the directory entries if requested and send them immediately. */
   if (want_contents)
     {
+      /* Use epoch for a placeholder for a missing date.  */
+      const char *missing_date = svn_time_to_cstring(0, pool);
+
       SVN_CMD_ERR(svn_fs_dir_entries(&entries, root, full_path, pool));
 
       /* Transform the hash table's FS entries into dirents.  This probably
@@ -1550,43 +1560,39 @@ static svn_error_t *get_dir(svn_ra_svn_c
         {
           const char *name = svn__apr_hash_index_key(hi);
           svn_fs_dirent_t *fsent = svn__apr_hash_index_val(hi);
-          svn_dirent_t *entry;
+          const char *file_path;
+
+          /* The fields in the entry tuple.  */
+          svn_node_kind_t entry_kind = svn_node_none;
+          svn_filesize_t entry_size = 0;
+          svn_boolean_t has_props = FALSE;
+          svn_revnum_t created_rev = 0; /* ### SVN_INVALID_REVNUM  */
+          const char *cdate = NULL;
+          const char *last_author = NULL;
 
           svn_pool_clear(subpool);
 
           file_path = svn_fspath__join(full_path, name, subpool);
-
           if (! lookup_access(subpool, b, conn, svn_authz_read,
                               file_path, FALSE))
-            {
-              apr_hash_set(entries, name, APR_HASH_KEY_STRING, NULL);
-              continue;
-            }
-
-          entry = apr_pcalloc(pool, sizeof(*entry));
+            continue;
 
           if (dirent_fields & SVN_DIRENT_KIND)
-            {
-              /* kind */
-              entry->kind = fsent->kind;
-            }
+              entry_kind = fsent->kind;
 
           if (dirent_fields & SVN_DIRENT_SIZE)
-            {
-              /* size */
-              if (entry->kind == svn_node_dir)
-                entry->size = 0;
-              else
-                SVN_CMD_ERR(svn_fs_file_length(&entry->size, root, file_path,
+              if (entry_kind != svn_node_dir)
+                SVN_CMD_ERR(svn_fs_file_length(&entry_size, root, file_path,
                                                subpool));
-            }
 
           if (dirent_fields & SVN_DIRENT_HAS_PROPS)
             {
+              apr_hash_t *file_props;
+
               /* has_props */
               SVN_CMD_ERR(svn_fs_node_proplist(&file_props, root, file_path,
                                                subpool));
-              entry->has_props = (apr_hash_count(file_props) > 0);
+              has_props = (apr_hash_count(file_props) > 0);
             }
 
           if ((dirent_fields & SVN_DIRENT_LAST_AUTHOR)
@@ -1594,47 +1600,33 @@ static svn_error_t *get_dir(svn_ra_svn_c
               || (dirent_fields & SVN_DIRENT_CREATED_REV))
             {
               /* created_rev, last_author, time */
-              SVN_CMD_ERR(svn_repos_get_committed_info(&entry->created_rev,
+              SVN_CMD_ERR(svn_repos_get_committed_info(&created_rev,
                                                        &cdate,
-                                                       &cauthor, root,
+                                                       &last_author,
+                                                       root,
                                                        file_path,
                                                        subpool));
-              entry->last_author = apr_pstrdup(pool, cauthor);
-              if (cdate)
-                SVN_CMD_ERR(svn_time_from_cstring(&entry->time, cdate,
-                                                  subpool));
-              else
-                entry->time = (time_t) -1;
             }
 
-          /* Store the entry. */
-          apr_hash_set(entries, name, APR_HASH_KEY_STRING, entry);
-        }
-      svn_pool_destroy(subpool);
-    }
+          /* The client does not properly handle a missing CDATE. For
+             interoperability purposes, we must fill in some junk.
 
-  /* Write out response. */
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(r(!", "success", rev));
-  SVN_ERR(svn_ra_svn_write_proplist(conn, pool, props));
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)(!"));
-  if (want_contents)
-    {
-      for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
-        {
-          const char *name = svn__apr_hash_index_key(hi);
-          svn_dirent_t *entry = svn__apr_hash_index_val(hi);
+             See libsvn_ra_svn/client.c:ra_svn_get_dir()  */
+          if (cdate == NULL)
+            cdate = missing_date;
 
-          cdate = (entry->time == (time_t) -1) ? NULL
-            : svn_time_to_cstring(entry->time, pool);
+          /* Send the entry. */
           SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "cwnbr(?c)(?c)", name,
-                                         svn_node_kind_to_word(entry->kind),
-                                         (apr_uint64_t) entry->size,
-                                         entry->has_props, entry->created_rev,
-                                         cdate, entry->last_author));
+                                         svn_node_kind_to_word(entry_kind),
+                                         (apr_uint64_t) entry_size,
+                                         has_props, created_rev,
+                                         cdate, last_author));
         }
+      svn_pool_destroy(subpool);
     }
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
-  return SVN_NO_ERROR;
+
+  /* Finish response. */
+  return svn_ra_svn_write_tuple(conn, pool, "!))");
 }
 
 static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
@@ -1979,7 +1971,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
   server_baton_t *b = baton;
   svn_revnum_t start_rev, end_rev;
   const char *full_path;
-  svn_boolean_t changed_paths, strict_node, include_merged_revisions;
+  svn_boolean_t send_changed_paths, strict_node, include_merged_revisions;
   apr_array_header_t *paths, *full_paths, *revprop_items, *revprops;
   char *revprop_word;
   svn_ra_svn_item_t *elt;
@@ -1988,7 +1980,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
   log_baton_t lb;
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)(?r)bb?n?Bwl", &paths,
-                                 &start_rev, &end_rev, &changed_paths,
+                                 &start_rev, &end_rev, &send_changed_paths,
                                  &strict_node, &limit,
                                  &include_merged_revs_param,
                                  &revprop_word, &revprop_items));
@@ -2045,7 +2037,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
 
   SVN_ERR(log_command(b, conn, pool, "%s",
                       svn_log__log(full_paths, start_rev, end_rev,
-                                   limit, changed_paths, strict_node,
+                                   limit, send_changed_paths, strict_node,
                                    include_merged_revisions, revprops,
                                    pool)));
 
@@ -2054,7 +2046,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
   lb.conn = conn;
   lb.stack_depth = 0;
   err = svn_repos_get_logs4(b->repos, full_paths, start_rev, end_rev,
-                            (int) limit, changed_paths, strict_node,
+                            (int) limit, send_changed_paths, strict_node,
                             include_merged_revisions, revprops,
                             authz_check_access_cb_func(b), b, log_receiver,
                             &lb, pool);
@@ -2947,6 +2939,24 @@ repos_path_valid(const char *path)
   return TRUE;
 }
 
+/* Callback which receives hook environment variables from the hook
+ * environment configuration section,
+ * An implementation of svn_config_enumerator2_t. */
+static svn_boolean_t
+hooks_env_conf_cb(const char *name,
+                  const char *value,
+                  void *baton,
+                  apr_pool_t *pool)
+{
+  apr_hash_t *hooks_env = baton;
+  apr_pool_t *hash_pool = apr_hash_pool_get(hooks_env);
+
+  apr_hash_set(hooks_env, apr_pstrdup(hash_pool, name),
+               APR_HASH_KEY_STRING, apr_pstrdup(hash_pool, value));
+
+  return TRUE;
+}
+
 /* Look for the repository given by URL, using ROOT as the virtual
  * repository root.  If we find one, fill in the repos, fs, cfg,
  * repos_url, and fs_path fields of B.  Set B->repos's client
@@ -3037,6 +3047,17 @@ static svn_error_t *find_repos(const cha
                                  "No access allowed to this repository",
                                  b, conn, pool);
 
+  /* If a hook environment has been configured, set it up. */
+  if (svn_config_has_section(b->cfg, SVN_CONFIG_SECTION_HOOKS_ENV))
+    {
+      apr_hash_t *hooks_env = apr_hash_make(pool);
+
+      svn_config_enumerate2(b->cfg, SVN_CONFIG_SECTION_HOOKS_ENV,
+                            hooks_env_conf_cb, hooks_env, pool);
+
+      svn_repos_hooks_setenv(b->repos, hooks_env);
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -3063,6 +3084,140 @@ fs_warning_func(void *baton, svn_error_t
   svn_pool_clear(b->pool);
 }
 
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  server_baton_t *sb = baton;
+  svn_fs_root_t *fs_root;
+  svn_error_t *err;
+
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    SVN_ERR(svn_fs_youngest_rev(&base_revision, sb->fs, scratch_pool));
+
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL. */
+      path = svn_uri_skip_ancestor(sb->repos_url, path, scratch_pool);
+      path = svn_fspath__canonicalize(path, scratch_pool);
+    }
+  else
+    {
+      /* This is a base-relative path. */
+      if (path[0] != '/')
+        /* Get an absolute path for use in the FS. */
+        path = svn_fspath__join(sb->fs_path->data, path, scratch_pool);
+    }
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, sb->fs, base_revision, scratch_pool));
+
+  err = svn_fs_node_proplist(props, fs_root, path, result_pool);
+  if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      *props = apr_hash_make(result_pool);
+      return SVN_NO_ERROR;
+    }
+  else if (err)
+    return svn_error_trace(err);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *scratch_pool)
+{
+  server_baton_t *sb = baton;
+  svn_node_kind_t node_kind;
+  svn_fs_root_t *fs_root;
+
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    SVN_ERR(svn_fs_youngest_rev(&base_revision, sb->fs, scratch_pool));
+
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL. */
+      path = svn_uri_skip_ancestor(sb->repos_url, path, scratch_pool);
+      path = svn_fspath__canonicalize(path, scratch_pool);
+    }
+  else
+    {
+      /* This is a base-relative path. */
+      if (path[0] != '/')
+        /* Get an absolute path for use in the FS. */
+        path = svn_fspath__join(sb->fs_path->data, path, scratch_pool);
+    }
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, sb->fs, base_revision, scratch_pool));
+
+  SVN_ERR(svn_fs_check_path(&node_kind, fs_root, path, scratch_pool));
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  server_baton_t *sb = baton;
+  svn_stream_t *contents;
+  svn_stream_t *file_stream;
+  const char *tmp_filename;
+  svn_fs_root_t *fs_root;
+  svn_error_t *err;
+
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    SVN_ERR(svn_fs_youngest_rev(&base_revision, sb->fs, scratch_pool));
+
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL. */
+      path = svn_uri_skip_ancestor(sb->repos_url, path, scratch_pool);
+      path = svn_fspath__canonicalize(path, scratch_pool);
+    }
+  else
+    {
+      /* This is a base-relative path. */
+      if (path[0] != '/')
+        /* Get an absolute path for use in the FS. */
+        path = svn_fspath__join(sb->fs_path->data, path, scratch_pool);
+    }
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, sb->fs, base_revision, scratch_pool));
+
+  err = svn_fs_file_contents(&contents, fs_root, path, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+  else if (err)
+    return svn_error_trace(err);
+  SVN_ERR(svn_stream_open_unique(&file_stream, &tmp_filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 scratch_pool, scratch_pool));
+  SVN_ERR(svn_stream_copy3(contents, file_stream, NULL, NULL, scratch_pool));
+
+  *filename = apr_pstrdup(result_pool, tmp_filename);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *serve(svn_ra_svn_conn_t *conn, serve_params_t *params,
                    apr_pool_t *pool)
 {
@@ -3094,6 +3249,8 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
                APR_HASH_KEY_STRING, params->cache_txdeltas ? "1" : "0");
   apr_hash_set(b.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                APR_HASH_KEY_STRING, params->cache_fulltexts ? "1" : "0");
+  apr_hash_set(b.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+               APR_HASH_KEY_STRING, params->cache_revprops ? "1" : "0");
 
   /* Send greeting.  We don't support version 1 any more, so we can
    * send an empty mechlist. */
@@ -3226,5 +3383,18 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
     SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
   }
 
+  /* Set up editor shims. */
+  {
+    svn_delta_shim_callbacks_t *callbacks =
+                                svn_delta_shim_callbacks_default(pool);
+
+    callbacks->fetch_base_func = fetch_base_func;
+    callbacks->fetch_props_func = fetch_props_func;
+    callbacks->fetch_kind_func = fetch_kind_func;
+    callbacks->fetch_baton = &b;
+
+    SVN_ERR(svn_ra_svn__set_shim_callbacks(conn, callbacks));
+  }
+
   return svn_ra_svn_handle_commands2(conn, pool, main_commands, &b, FALSE);
 }

Modified: subversion/branches/javahl-ra/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/server.h?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/server.h (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/server.h Mon Apr 23 12:32:48 2012
@@ -116,6 +116,9 @@ typedef struct serve_params_t {
   /* Enable full-text caching for all FSFS repositories. */
   svn_boolean_t cache_fulltexts;
 
+  /* Enable revprop caching for all FSFS repositories. */
+  svn_boolean_t cache_revprops;
+
   /* Size of the in-memory cache (used by FSFS only). */
   apr_uint64_t memory_cache_size;
 



Mime
View raw message