subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From as...@apache.org
Subject svn commit: r1413258 [31/33] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/ notes/ notes/directory-index/ subversion/ subv...
Date Sat, 24 Nov 2012 20:29:48 GMT
Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-export-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-export-cmd.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-export-cmd.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-export-cmd.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,344 @@
+/*
+ * export-cmd.c -- Subversion export command
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include "svn_client.h"
+#include "svn_error.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_cmdline.h"
+#include "cl.h"
+
+#include "svn_private_config.h"
+#include "private/svn_string_private.h"
+#include "private/svn_client_private.h"
+
+/*** The export editor code. ***/
+
+/* ---------------------------------------------------------------------- */
+
+/*** A dedicated 'export' editor, which does no .svn/ accounting.  ***/
+
+typedef struct edit_baton_t
+{
+  apr_int64_t file_count;
+  apr_int64_t dir_count;
+  apr_int64_t byte_count;
+  apr_int64_t prop_count;
+  apr_int64_t prop_byte_count;
+} edit_baton_t;
+
+static svn_error_t *
+set_target_revision(void *edit_baton,
+                    svn_revnum_t target_revision,
+                    apr_pool_t *pool)
+{
+  return SVN_NO_ERROR;
+}
+
+
+/* Just ensure that the main export directory exists. */
+static svn_error_t *
+open_root(void *edit_baton,
+          svn_revnum_t base_revision,
+          apr_pool_t *pool,
+          void **root_baton)
+{
+  *root_baton = edit_baton;
+  return SVN_NO_ERROR;
+}
+
+
+/* Ensure the directory exists, and send feedback. */
+static svn_error_t *
+add_directory(const char *path,
+              void *parent_baton,
+              const char *copyfrom_path,
+              svn_revnum_t copyfrom_revision,
+              apr_pool_t *pool,
+              void **baton)
+{
+  edit_baton_t *eb = parent_baton;
+  eb->dir_count++;
+
+  *baton = parent_baton;
+  return SVN_NO_ERROR;
+}
+
+
+/* Build a file baton. */
+static svn_error_t *
+add_file(const char *path,
+          void *parent_baton,
+          const char *copyfrom_path,
+          svn_revnum_t copyfrom_revision,
+          apr_pool_t *pool,
+          void **baton)
+{
+  edit_baton_t *eb = parent_baton;
+  eb->file_count++;
+
+  *baton = parent_baton;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+window_handler(svn_txdelta_window_t *window, void *baton)
+{
+  edit_baton_t *eb = baton;
+  if (window != NULL)
+    eb->byte_count += window->tview_len;
+
+  return SVN_NO_ERROR;
+}
+
+/* Write incoming data into the tmpfile stream */
+
+static svn_error_t *
+apply_textdelta(void *file_baton,
+                const char *base_checksum,
+                apr_pool_t *pool,
+                svn_txdelta_window_handler_t *handler,
+                void **handler_baton)
+{
+  *handler_baton = file_baton;
+  *handler = window_handler;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+change_file_prop(void *file_baton,
+                 const char *name,
+                 const svn_string_t *value,
+                 apr_pool_t *pool)
+{
+  edit_baton_t *eb = file_baton;
+  eb->prop_count++;
+  eb->prop_byte_count += value->len;
+  
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+change_dir_prop(void *dir_baton,
+                const char *name,
+                const svn_string_t *value,
+                apr_pool_t *pool)
+{
+  edit_baton_t *eb = dir_baton;
+  eb->prop_count++;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+close_file(void *file_baton,
+           const char *text_checksum,
+           apr_pool_t *pool)
+{
+  return SVN_NO_ERROR;
+}
+
+
+/*** Public Interfaces ***/
+
+static svn_error_t *
+bench_null_export(svn_revnum_t *result_rev,
+                  const char *from_path_or_url,
+                  svn_opt_revision_t *peg_revision,
+                  svn_opt_revision_t *revision,
+                  svn_depth_t depth,
+                  void *baton,
+                  svn_client_ctx_t *ctx,
+                  svn_boolean_t quiet,
+                  apr_pool_t *pool)
+{
+  svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
+  svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url);
+
+  SVN_ERR_ASSERT(peg_revision != NULL);
+  SVN_ERR_ASSERT(revision != NULL);
+
+  if (peg_revision->kind == svn_opt_revision_unspecified)
+    peg_revision->kind = svn_path_is_url(from_path_or_url)
+                       ? svn_opt_revision_head
+                       : svn_opt_revision_working;
+
+  if (revision->kind == svn_opt_revision_unspecified)
+    revision = peg_revision;
+
+  if (from_is_url || ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
+    {
+      svn_client__pathrev_t *loc;
+      svn_ra_session_t *ra_session;
+      svn_node_kind_t kind;
+
+      /* Get the RA connection. */
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+                                                from_path_or_url, NULL,
+                                                peg_revision,
+                                                revision, ctx, pool));
+
+      SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, pool));
+
+      if (kind == svn_node_file)
+        {
+          apr_hash_t *props;
+
+          /* Since you cannot actually root an editor at a file, we
+           * manually drive a few functions of our editor. */
+
+          /* Step outside the editor-likeness for a moment, to actually talk
+           * to the repository. */
+          /* ### note: the stream will not be closed */
+          SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev,
+                                  svn_stream_empty(pool),
+                                  NULL, &props, pool));
+        }
+      else if (kind == svn_node_dir)
+        {
+          void *edit_baton = NULL;
+          const svn_delta_editor_t *export_editor = NULL;
+          const svn_ra_reporter3_t *reporter;
+          void *report_baton;
+
+          svn_delta_editor_t *editor = svn_delta_default_editor(pool);
+
+          editor->set_target_revision = set_target_revision;
+          editor->open_root = open_root;
+          editor->add_directory = add_directory;
+          editor->add_file = add_file;
+          editor->apply_textdelta = apply_textdelta;
+          editor->close_file = close_file;
+          editor->change_file_prop = change_file_prop;
+          editor->change_dir_prop = change_dir_prop;
+
+          /* for ra_svn, we don't need an editior in quiet mode */
+          if (!quiet || strncmp(loc->repos_root_url, "svn:", 4))
+            SVN_ERR(svn_delta_get_cancellation_editor(ctx->cancel_func,
+                                                      ctx->cancel_baton,
+                                                      editor,
+                                                      baton,
+                                                      &export_editor,
+                                                      &edit_baton,
+                                                      pool));
+
+          /* Manufacture a basic 'report' to the update reporter. */
+          SVN_ERR(svn_ra_do_update2(ra_session,
+                                    &reporter, &report_baton,
+                                    loc->rev,
+                                    "", /* no sub-target */
+                                    depth,
+                                    FALSE, /* don't want copyfrom-args */
+                                    export_editor, edit_baton, pool));
+
+          SVN_ERR(reporter->set_path(report_baton, "", loc->rev,
+                                     /* Depth is irrelevant, as we're
+                                        passing start_empty=TRUE anyway. */
+                                     svn_depth_infinity,
+                                     TRUE, /* "help, my dir is empty!" */
+                                     NULL, pool));
+
+          SVN_ERR(reporter->finish_report(report_baton, pool));
+        }
+      else if (kind == svn_node_none)
+        {
+          return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                                   _("URL '%s' doesn't exist"),
+                                   from_path_or_url);
+        }
+      /* kind == svn_node_unknown not handled */
+    }
+
+
+  if (result_rev)
+    *result_rev = edit_revision;
+
+  return SVN_NO_ERROR;
+}
+
+
+/*** Code. ***/
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__null_export(apr_getopt_t *os,
+                    void *baton,
+                    apr_pool_t *pool)
+{
+  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+  const char *from;
+  apr_array_header_t *targets;
+  svn_error_t *err;
+  svn_opt_revision_t peg_revision;
+  const char *truefrom;
+  edit_baton_t eb = { 0 };
+
+  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+                                                      opt_state->targets,
+                                                      ctx, FALSE, pool));
+
+  /* We want exactly 1 or 2 targets for this subcommand. */
+  if (targets->nelts < 1)
+    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
+  if (targets->nelts > 2)
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
+
+  /* The first target is the `from' path. */
+  from = APR_ARRAY_IDX(targets, 0, const char *);
+
+  /* Get the peg revision if present. */
+  SVN_ERR(svn_opt_parse_path(&peg_revision, &truefrom, from, pool));
+
+  if (opt_state->depth == svn_depth_unknown)
+    opt_state->depth = svn_depth_infinity;
+
+  /* Do the export. */
+  err = bench_null_export(NULL, truefrom, &peg_revision,
+                          &(opt_state->start_revision),
+                          opt_state->depth,
+                          &eb,
+                          ctx, opt_state->quiet, pool);
+
+  if (!opt_state->quiet)
+    SVN_ERR(svn_cmdline_printf(pool,
+                               _("%15s directories\n"
+                                 "%15s files\n"
+                                 "%15s bytes in files\n"
+                                 "%15s properties\n"
+                                 "%15s bytes in properties\n"),
+                               svn__ui64toa_sep(eb.dir_count, ',', pool),
+                               svn__ui64toa_sep(eb.file_count, ',', pool),
+                               svn__ui64toa_sep(eb.byte_count, ',', pool),
+                               svn__ui64toa_sep(eb.prop_count, ',', pool),
+                               svn__ui64toa_sep(eb.prop_byte_count, ',', pool)));
+
+  return svn_error_trace(err);
+}

Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-list-cmd.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-list-cmd.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-list-cmd.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,166 @@
+/*
+ * list-cmd.c -- list a URL
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include "svn_cmdline.h"
+#include "svn_client.h"
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "svn_time.h"
+#include "svn_xml.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_utf.h"
+#include "svn_opt.h"
+
+#include "cl.h"
+
+#include "svn_private_config.h"
+#include "private/svn_string_private.h"
+
+
+
+/* Baton used when printing directory entries. */
+struct print_baton {
+  svn_boolean_t verbose;
+  apr_int64_t directories;
+  apr_int64_t files;
+  apr_int64_t locks;
+  svn_client_ctx_t *ctx;
+};
+
+/* This implements the svn_client_list_func_t API, printing a single
+   directory entry in text format. */
+static svn_error_t *
+print_dirent(void *baton,
+             const char *path,
+             const svn_dirent_t *dirent,
+             const svn_lock_t *lock,
+             const char *abs_path,
+             apr_pool_t *pool)
+{
+  struct print_baton *pb = baton;
+
+  if (pb->ctx->cancel_func)
+    SVN_ERR(pb->ctx->cancel_func(pb->ctx->cancel_baton));
+
+  if (dirent->kind == svn_node_dir)
+    pb->directories++;
+  if (dirent->kind == svn_node_file)
+    pb->files++;
+  if (lock)
+    pb->locks++;
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__null_list(apr_getopt_t *os,
+                  void *baton,
+                  apr_pool_t *pool)
+{
+  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+  apr_array_header_t *targets;
+  int i;
+  apr_pool_t *subpool = svn_pool_create(pool);
+  apr_uint32_t dirent_fields;
+  struct print_baton pb = { FALSE };
+  svn_boolean_t seen_nonexistent_target = FALSE;
+  svn_error_t *err;
+
+  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+                                                      opt_state->targets,
+                                                      ctx, FALSE, pool));
+
+  /* Add "." if user passed 0 arguments */
+  svn_opt_push_implicit_dot_target(targets, pool);
+
+  if (opt_state->verbose)
+    dirent_fields = SVN_DIRENT_ALL;
+  else
+    dirent_fields = SVN_DIRENT_KIND; /* the only thing we actually need... */
+
+  pb.ctx = ctx;
+  pb.verbose = opt_state->verbose;
+
+  if (opt_state->depth == svn_depth_unknown)
+    opt_state->depth = svn_depth_immediates;
+
+  /* For each target, try to list it. */
+  for (i = 0; i < targets->nelts; i++)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+      const char *truepath;
+      svn_opt_revision_t peg_revision;
+
+      svn_pool_clear(subpool);
+
+      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
+
+      /* Get peg revisions. */
+      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
+                                 subpool));
+
+      err = svn_client_list2(truepath, &peg_revision,
+                             &(opt_state->start_revision),
+                             opt_state->depth,
+                             dirent_fields,
+                             opt_state->verbose,
+                             print_dirent,
+                             &pb, ctx, subpool);
+
+      if (err)
+        {
+          /* If one of the targets is a non-existent URL or wc-entry,
+             don't bail out.  Just warn and move on to the next target. */
+          if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
+              err->apr_err == SVN_ERR_FS_NOT_FOUND)
+              svn_handle_warning2(stderr, err, "svn-bench: ");
+          else
+              return svn_error_trace(err);
+
+          svn_error_clear(err);
+          err = NULL;
+          seen_nonexistent_target = TRUE;
+        }
+      else if (!opt_state->quiet)
+        SVN_ERR(svn_cmdline_printf(pool,
+                                   _("%15s directories\n"
+                                     "%15s files\n"
+                                     "%15s locks\n"),
+                                   svn__ui64toa_sep(pb.directories, ',', pool),
+                                   svn__ui64toa_sep(pb.files, ',', pool),
+                                   svn__ui64toa_sep(pb.locks, ',', pool)));
+    }
+
+  svn_pool_destroy(subpool);
+
+  if (seen_nonexistent_target)
+    return svn_error_create(
+      SVN_ERR_ILLEGAL_TARGET, NULL,
+      _("Could not list all targets because some targets don't exist"));
+  else
+    return SVN_NO_ERROR;
+}

Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-log-cmd.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-log-cmd.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/null-log-cmd.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,242 @@
+/*
+ * log-cmd.c -- Display log messages
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#define APR_WANT_STRFUNC
+#define APR_WANT_STDIO
+#include <apr_want.h>
+
+#include "svn_cmdline.h"
+#include "svn_compat.h"
+#include "svn_path.h"
+#include "svn_props.h"
+
+#include "cl.h"
+
+#include "svn_private_config.h"
+#include "private/svn_string_private.h"
+
+
+/*** Code. ***/
+
+/* Baton for log_entry_receiver() and log_entry_receiver_xml(). */
+struct log_receiver_baton
+{
+  /* Client context. */
+  svn_client_ctx_t *ctx;
+
+  /* Level of merge revision nesting */
+  apr_size_t merge_depth;
+
+  /* collect counters? */
+  svn_boolean_t quiet;
+
+  /* total revision counters */
+  apr_int64_t revisions;
+  apr_int64_t changes;
+  apr_int64_t message_lines;
+
+  /* part that came from merges */
+  apr_int64_t merges;
+  apr_int64_t merged_revs;
+  apr_int64_t merged_changes;
+  apr_int64_t merged_message_lines;
+};
+
+
+/* Implement `svn_log_entry_receiver_t', printing the logs in
+ * a human-readable and machine-parseable format.
+ *
+ * BATON is of type `struct log_receiver_baton'.
+ */
+static svn_error_t *
+log_entry_receiver(void *baton,
+                   svn_log_entry_t *log_entry,
+                   apr_pool_t *pool)
+{
+  struct log_receiver_baton *lb = baton;
+  const char *author;
+  const char *date;
+  const char *message;
+
+  if (lb->ctx->cancel_func)
+    SVN_ERR(lb->ctx->cancel_func(lb->ctx->cancel_baton));
+
+  if (! SVN_IS_VALID_REVNUM(log_entry->revision))
+    {
+      lb->merge_depth--;
+      return SVN_NO_ERROR;
+    }
+
+  /* if we don't want counters, we are done */
+  if (lb->quiet)
+    return SVN_NO_ERROR;
+
+  /* extract the message and do all the other counting */
+  svn_compat_log_revprops_out(&author, &date, &message, log_entry->revprops);
+  if (log_entry->revision == 0 && message == NULL)
+    return SVN_NO_ERROR;
+  
+  lb->revisions++;
+  if (lb->merge_depth)
+    lb->merged_revs++;
+
+  if (message != NULL)
+    {
+      int count = svn_cstring_count_newlines(message) + 1;
+      lb->message_lines += count;
+      if (lb->merge_depth)
+        lb->merged_message_lines += count;
+    }
+
+  if (log_entry->changed_paths2)
+    {
+      unsigned count = apr_hash_count(log_entry->changed_paths2);
+      lb->changes += count;
+      if (lb->merge_depth)
+        lb->merged_changes += count;
+    }
+
+  if (log_entry->has_children)
+    {
+      lb->merge_depth++;
+      lb->merges++;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__null_log(apr_getopt_t *os,
+                 void *baton,
+                 apr_pool_t *pool)
+{
+  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+  apr_array_header_t *targets;
+  struct log_receiver_baton lb = { ctx };
+  const char *target;
+  int i;
+  apr_array_header_t *revprops;
+  svn_opt_revision_t target_peg_revision;
+  const char *target_path_or_url;
+
+  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+                                                      opt_state->targets,
+                                                      ctx, FALSE, pool));
+
+  /* Add "." if user passed 0 arguments */
+  svn_opt_push_implicit_dot_target(targets, pool);
+
+  /* Determine if they really want a two-revision range. */
+  if (opt_state->used_change_arg)
+    {
+      if (opt_state->used_revision_arg && opt_state->revision_ranges->nelts > 1)
+        {
+          return svn_error_create
+            (SVN_ERR_CLIENT_BAD_REVISION, NULL,
+             _("-c and -r are mutually exclusive"));
+        }
+      for (i = 0; i < opt_state->revision_ranges->nelts; i++)
+        {
+          svn_opt_revision_range_t *range;
+          range = APR_ARRAY_IDX(opt_state->revision_ranges, i,
+                                svn_opt_revision_range_t *);
+          if (range->start.value.number < range->end.value.number)
+            range->start.value.number++;
+          else
+            range->end.value.number++;
+        }
+    }
+
+  /* Parse the first target into path-or-url and peg revision. */
+  target = APR_ARRAY_IDX(targets, 0, const char *);
+  SVN_ERR(svn_opt_parse_path(&target_peg_revision, &target_path_or_url,
+                             target, pool));
+  if (target_peg_revision.kind == svn_opt_revision_unspecified)
+    target_peg_revision.kind = (svn_path_is_url(target)
+                                     ? svn_opt_revision_head
+                                     : svn_opt_revision_working);
+  APR_ARRAY_IDX(targets, 0, const char *) = target_path_or_url;
+
+  if (svn_path_is_url(target))
+    {
+      for (i = 1; i < targets->nelts; i++)
+        {
+          target = APR_ARRAY_IDX(targets, i, const char *);
+
+          if (svn_path_is_url(target) || target[0] == '/')
+            return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                     _("Only relative paths can be specified"
+                                       " after a URL for 'svn-bench log', "
+                                       "but '%s' is not a relative path"),
+                                     target);
+        }
+    }
+
+  lb.quiet = opt_state->quiet;
+
+  revprops = apr_array_make(pool, 3, sizeof(char *));
+  APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR;
+  APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE;
+  if (!opt_state->quiet)
+    APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG;
+  SVN_ERR(svn_client_log5(targets,
+                          &target_peg_revision,
+                          opt_state->revision_ranges,
+                          opt_state->limit,
+                          opt_state->verbose,
+                          opt_state->stop_on_copy,
+                          opt_state->use_merge_history,
+                          revprops,
+                          log_entry_receiver,
+                          &lb,
+                          ctx,
+                          pool));
+
+  if (!opt_state->quiet)
+    {
+      if (opt_state->use_merge_history)
+        SVN_ERR(svn_cmdline_printf(pool,
+                      _("%15s revisions, %15s merged in %s merges\n"
+                        "%15s msg lines, %15s in merged revisions\n"
+                        "%15s changes,   %15s in merged revisions\n"),
+                      svn__ui64toa_sep(lb.revisions, ',', pool),
+                      svn__ui64toa_sep(lb.merged_revs, ',', pool),
+                      svn__ui64toa_sep(lb.merges, ',', pool),
+                      svn__ui64toa_sep(lb.message_lines, ',', pool),
+                      svn__ui64toa_sep(lb.merged_message_lines, ',', pool),
+                      svn__ui64toa_sep(lb.changes, ',', pool),
+                      svn__ui64toa_sep(lb.merged_changes, ',', pool)));
+      else
+        SVN_ERR(svn_cmdline_printf(pool,
+                      _("%15s revisions\n"
+                        "%15s msg lines\n"
+                        "%15s changes\n"),
+                      svn__ui64toa_sep(lb.revisions, ',', pool),
+                      svn__ui64toa_sep(lb.message_lines, ',', pool),
+                      svn__ui64toa_sep(lb.changes, ',', pool)));
+    }
+
+  return SVN_NO_ERROR;
+}

Added: subversion/branches/compressed-pristines/tools/client-side/svn-bench/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/client-side/svn-bench/util.c?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/client-side/svn-bench/util.c (added)
+++ subversion/branches/compressed-pristines/tools/client-side/svn-bench/util.c Sat Nov 24 20:29:11 2012
@@ -0,0 +1,92 @@
+/*
+ * util.c: Subversion command line client utility functions. Any
+ * functions that need to be shared across subcommands should be put
+ * in here.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "svn_private_config.h"
+#include "svn_error.h"
+#include "svn_path.h"
+
+#include "cl.h"
+
+
+
+svn_error_t *
+svn_cl__args_to_target_array_print_reserved(apr_array_header_t **targets,
+                                            apr_getopt_t *os,
+                                            const apr_array_header_t *known_targets,
+                                            svn_client_ctx_t *ctx,
+                                            svn_boolean_t keep_last_origpath_on_truepath_collision,
+                                            apr_pool_t *pool)
+{
+  svn_error_t *err = svn_client_args_to_target_array2(targets,
+                                                      os,
+                                                      known_targets,
+                                                      ctx,
+                                                      keep_last_origpath_on_truepath_collision,
+                                                      pool);
+  if (err)
+    {
+      if (err->apr_err ==  SVN_ERR_RESERVED_FILENAME_SPECIFIED)
+        {
+          svn_handle_error2(err, stderr, FALSE, "svn: Skipping argument: ");
+          svn_error_clear(err);
+        }
+      else
+        return svn_error_trace(err);
+    }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cl__check_target_is_local_path(const char *target)
+{
+  if (svn_path_is_url(target))
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("'%s' is not a local path"), target);
+  return SVN_NO_ERROR;
+}
+
+const char *
+svn_cl__local_style_skip_ancestor(const char *parent_path,
+                                  const char *path,
+                                  apr_pool_t *pool)
+{
+  const char *relpath = NULL;
+
+  if (parent_path)
+    relpath = svn_dirent_skip_ancestor(parent_path, path);
+
+  return svn_dirent_local_style(relpath ? relpath : path, pool);
+}
+

Modified: subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/benchmark.py
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/benchmark.py?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/benchmark.py (original)
+++ subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/benchmark.py Sat Nov 24 20:29:11 2012
@@ -17,25 +17,52 @@
 # specific language governing permissions and limitations
 # under the License.
 
-"""Usage: benchmark.py run|list|compare|show|chart ...
+"""Usage: benchmark.py run|list|compare|show|chart <selection> ...
+
+SELECTING TIMINGS -- B@R,LxS
+ 
+In the subcommands below, a timings selection consists of a string with up to
+four elements:
+  <branch>@<revision>,<levels>x<spread> 
+abbreviated as:
+  B@R,LxS
+
+<branch> is a label of an svn branch, e.g. "1.7.x".
+<revision> is the last-changed-revision of above branch.
+<levels> is the number of directory levels created in the benchmark.
+<spread> is the number of child trees spreading off each dir level.
+
+<branch_name> and <revision> are simply used for labeling. Upon the actual
+test runs, you should enter labels matching the selected --svn-bin-dir.
+Later, you can select runs individually by using these labels.
+
+For <revision>, you can provide special keywords:
+- 'each' has the same effect as entering each available revision number that
+  is on record in the db in a separate timings selection.
+- 'last' is the same as 'each', but shows only the last 10 revisions. 'last'
+  can be combined with a number, e.g. 'last12'.
+
+For all subcommands except 'run', you can omit some or all of the elements of
+a timings selection to combine all available timings sets. Try that out with
+the 'list' subcommand.
+
+Examples:
+  benchmark.py run 1.7.x@12345,5x5
+  benchmark.py show trunk@12345
+  benchmark.py compare 1.7.0,1x100 trunk@each,1x100
+  benchmark.py chart compare 1.7.0,5x5 trunk@last12,5x5
+
 
 RUN BENCHMARKS
 
-  benchmark.py run <branch>@<revision>,<levels>x<spread> [N] [options]
+  benchmark.py run B@R,LxS [N] [options]
 
 Test data is added to an sqlite database created automatically, by default
 'benchmark.db' in the current working directory. To specify a different path,
 use option -f <path_to_db>.
 
-<branch_name> is a label of the svn branch you're testing, e.g. "1.7.x".
-<revision> is the last-changed-revision of above branch.
-<levels> is the number of directory levels to create
-<spread> is the number of child trees spreading off each dir level
 If <N> is provided, the run is repeated N times.
 
-<branch_name> and <revision> are simply used for later reference. You
-should enter labels matching the selected --svn-bin-dir.
-
 <levels> and <spread> control the way the tested working copy is structured:
   <levels>: number of directory levels to create.
   <spread>: number of files and subdirectories created in each dir.
@@ -43,22 +70,21 @@ should enter labels matching the selecte
 
 LIST WHAT IS ON RECORD
 
-  benchmark.py list [ <branch>@<rev>,<levels>x<spread> ]
+  benchmark.py list [B@R,LxS]
 
 Find entries in the database for the given constraints. Any arguments can
 be omitted. (To select only a rev, start with a '@', like '@123'; to select
 only spread, start with an 'x', like "x100".)
 
-Omit all args to get a listing of all available distinct entries.
+Call without arguments to get a listing of all available constraints.
 
 
 COMPARE TIMINGS
 
-  benchmark.py compare B@R,LxS B@R,LxS
+  benchmark.py compare B@R,LxS B@R,LxS [B@R,LxS [...]]
 
-Compare two kinds of timings (in text mode). Each B@R,LxS selects
-timings from branch, revision, WC-levels and -spread by the same labels as
-previously given for a 'run' call. Any elements can be omitted. For example:
+Compare any number of timings sets to the first provided set (in text mode).
+For example:
   benchmark.py compare 1.7.0 trunk@1349903
     Compare the total timings of all combined '1.7.0' branch runs to
     all combined runs of 'trunk'-at-revision-1349903.
@@ -66,38 +92,38 @@ previously given for a 'run' call. Any e
     Same as above, but only compare the working copy types with 5 levels
     and a spread of 5.
 
+Use the -c option to limit comparison to specific command names.
+
 
 SHOW TIMINGS
 
-  benchmark.py show <branch>@<rev>,<levels>x<spread>
+  benchmark.py show B@R,LxS [B@R,LxS [...]]
 
 Print out a summary of the timings selected from the given constraints.
-Any arguments can be omitted (like for the 'list' command).
 
 
 GENERATE CHARTS
 
   benchmark.py chart compare B@R,LxS B@R,LxS [ B@R,LxS ... ]
 
-Produce a bar chart that compares any number of sets of timings. Timing sets
-are supplied by B@R,LxS arguments (i.e. <branch>@<rev>,<levels>x<spread> as
-provided for a 'run' call), where any number of elements may be omitted. The
-less constraints you supply, the more timings are included (try it out with
-the 'list' command). The first set is taken as a reference point for 100% and
-+0 seconds. Each following dataset produces a set of labeled bar charts.
-So, at least two constraint arguments must be provided.
+Produce a bar chart that compares any number of sets of timings.  Like with
+the plain 'compare' command, the first set is taken as a reference point for
+100% and +-0 seconds. Each following dataset produces a set of labeled bar
+charts, grouped by svn command names. At least two timings sets must be
+provided.
 
-Use the -c option to limit charts to specific command names.
+Use the -c option to limit comparison to specific command names.
 
 
 EXAMPLES
 
-# Run 3 benchmarks on svn 1.7.0. Timings are saved in benchmark.db.
+# Run 3 benchmarks on svn 1.7.0 with 5 dir levels and 5 files and subdirs for
+# each level (spread). Timings are saved in ./benchmark.db.
 # Provide label '1.7.0' and its Last-Changed-Rev for later reference.
-# (You may also set your $PATH instead of using --svn-bin-dir.)
 ./benchmark.py run --svn-bin-dir ~/svn-prefix/1.7.0/bin 1.7.0@1181106,5x5 3
 
 # Record 3 benchmark runs on trunk, again naming its Last-Changed-Rev.
+# (You may also set your $PATH instead of using --svn-bin-dir.)
 ./benchmark.py run --svn-bin-dir ~/svn-prefix/trunk/bin trunk@1352725,5x5 3
 
 # Work with the results of above two runs
@@ -129,12 +155,18 @@ import random
 import shutil
 import stat
 import string
+from copy import copy
 
 IGNORE_COMMANDS = ('--version', )
 TOTAL_RUN = 'TOTAL RUN'
 
 j = os.path.join
 
+def bail(msg=None):
+  if msg:
+    print msg
+  exit(1)
+
 def time_str():
   return time.strftime('%Y-%m-%d %H:%M:%S');
 
@@ -227,6 +259,7 @@ class RunKind:
     if self.levels: self.levels = int(self.levels)
     if self.spread: self.spread = int(self.spread)
 
+  def label(self):
     label_parts = []
     if self.branch:
       label_parts.append(self.branch)
@@ -240,12 +273,52 @@ class RunKind:
       if self.spread:
         label_parts.append(RUN_KIND_SEPARATORS[2])
         label_parts.append(str(self.spread))
-    self.label = ''.join(label_parts)
+    return ''.join(label_parts)
 
   def args(self):
     return (self.branch, self.revision, self.levels, self.spread)
 
 
+def parse_timings_selections(db, *args):
+  run_kinds = []
+
+  for arg in args:
+    run_kind = RunKind(arg)
+
+    if run_kind.revision == 'each':
+      run_kind.revision = None
+      query = TimingQuery(db, run_kind)
+      for revision in query.get_sorted_revisions():
+        revision_run_kind = copy(run_kind)
+        revision_run_kind.revision = revision
+        run_kinds.append(revision_run_kind)
+    elif run_kind.revision and run_kind.revision.startswith('last'):
+      Nstr = run_kind.revision[4:]
+      if not Nstr:
+        N = 10
+      else:
+        N = int(Nstr)
+      run_kind.revision = None
+      query = TimingQuery(db, run_kind)
+      for revision in query.get_sorted_revisions()[-N:]:
+        revision_run_kind = copy(run_kind)
+        revision_run_kind.revision = revision
+        run_kinds.append(revision_run_kind)
+    else:
+      run_kinds.append(run_kind)
+
+  return run_kinds
+  
+def parse_one_timing_selection(db, *args):
+  run_kinds = parse_timings_selections(db, *args)
+  if len(run_kinds) != 1:
+    bail("I need exactly one timings identifier, not '%s'"
+         % (' '.join(*args)))
+  return run_kinds[0]
+
+
+
+
 PATHNAME_VALID_CHARS = "-_.,@%s%s" % (string.ascii_letters, string.digits)
 def filesystem_safe_string(s):
   return ''.join(c for c in s if c in PATHNAME_VALID_CHARS)
@@ -436,15 +509,19 @@ class TimingQuery:
               AND b.batch_id = r.batch_id
               AND r.aborted = 0
          """
-    self.append_constraint('k', 'branch', run_kind.branch)
-    self.append_constraint('k', 'revision', run_kind.revision)
-    self.append_constraint('k', 'wc_levels', run_kind.levels)
-    self.append_constraint('k', 'wc_spread', run_kind.spread)
-    self.label = run_kind.label
+    self.append_constraint('k.branch', run_kind.branch)
+    self.each_revision = False
+    if run_kind.revision == 'each':
+      self.each_revision = True
+    else:
+      self.append_constraint('k.revision', run_kind.revision)
+    self.append_constraint('k.wc_levels', run_kind.levels)
+    self.append_constraint('k.wc_spread', run_kind.spread)
+    self.label = run_kind.label()
 
-  def append_constraint(self, table, name, val):
+  def append_constraint(self, column_name, val):
     if val:
-      self.constraints.append('AND %s.%s = ?' % (table, name))
+      self.constraints.append('AND %s = ?' % column_name)
       self.values.append(val)
 
   def remove_last_constraint(self):
@@ -458,7 +535,6 @@ class TimingQuery:
     query.append('ORDER BY %s' % x)
     c = db.conn.cursor()
     try:
-      #print ' '.join(query)
       c.execute(' '.join(query), self.values)
       if n == 1:
         return [tpl[0] for tpl in c.fetchall()]
@@ -500,7 +576,7 @@ class TimingQuery:
                   max(t.timing),
                   avg(t.timing)""",
              self.FROM_WHERE ]
-    self.append_constraint('t', 'command', command)
+    self.append_constraint('t.command', command)
     try:
       query.extend(self.constraints)
       c = db.conn.cursor()
@@ -816,11 +892,12 @@ def perform_run(batch, run_kind,
 
     
 def cmdline_run(db, options, run_kind_str, N=1):
-  run_kind = RunKind(run_kind_str)
+  run_kind = parse_one_timing_selection(db, run_kind_str)
+    
   N = int(N)
 
   print 'Hi, going to run a Subversion benchmark series of %d runs...' % N
-  print 'Label is %s' % run_kind.label
+  print 'Label is %s' % run_kind.label()
 
   # can we run the svn binaries?
   svn_bin = j(options.svn_bin_dir, 'svn')
@@ -829,8 +906,7 @@ def cmdline_run(db, options, run_kind_st
   for b in (svn_bin, svnadmin_bin):
     so,se = run_cmd([b, '--version'])
     if not so:
-      print "Can't run", b
-      exit(1)
+      bail("Can't run %s" % b)
 
     print ', '.join([s.strip() for s in so.split('\n')[:2]])
 
@@ -844,54 +920,55 @@ def cmdline_run(db, options, run_kind_st
   batch.done()
 
 
-def cmdline_list(db, options, run_kind_str=None):
-  run_kind = RunKind(run_kind_str)
+def cmdline_list(db, options, *args):
+  run_kinds = parse_timings_selections(db, *args)
 
-  constraints = []
-  def add_if_not_none(name, val):
-    if val:
-      constraints.append('  %s = %s' % (name, val))
-  add_if_not_none('branch', run_kind.branch)
-  add_if_not_none('revision', run_kind.revision)
-  add_if_not_none('levels', run_kind.levels)
-  add_if_not_none('spread', run_kind.spread)
-  if constraints:
-    print 'For\n', '\n'.join(constraints)
-  print 'I found:'
+  for run_kind in run_kinds:
 
-  d = TimingQuery(db, run_kind)
-  
-  cmd_names = d.get_sorted_command_names()
-  if cmd_names:
-    print '\n%d command names:\n ' % len(cmd_names), '\n  '.join(cmd_names)
-
-  branches = d.get_sorted_branches()
-  if branches and (len(branches) > 1 or branches[0] != run_kind.branch):
-    print '\n%d branches:\n ' % len(branches), '\n  '.join(branches)
-
-  revisions = d.get_sorted_revisions()
-  if revisions and (len(revisions) > 1 or revisions[0] != run_kind.revision):
-    print '\n%d revisions:\n ' % len(revisions), '\n  '.join(revisions)
-
-  levels_spread = d.get_sorted_levels_spread()
-  if levels_spread and (
-       len(levels_spread) > 1
-       or levels_spread[0] != (run_kind.levels, run_kind.spread)):
-    print '\n%d kinds of levels x spread:\n ' % len(levels_spread), '\n  '.join(
-            [ ('%dx%d' % (l, s)) for l,s in levels_spread ])
+    constraints = []
+    def add_if_not_none(name, val):
+      if val:
+        constraints.append('  %s = %s' % (name, val))
+    add_if_not_none('branch', run_kind.branch)
+    add_if_not_none('revision', run_kind.revision)
+    add_if_not_none('levels', run_kind.levels)
+    add_if_not_none('spread', run_kind.spread)
+    if constraints:
+      print 'For\n', '\n'.join(constraints)
+    print 'I found:'
 
-  print "\n%d runs in %d batches.\n" % (d.count_runs_batches())
+    d = TimingQuery(db, run_kind)
+    
+    cmd_names = d.get_sorted_command_names()
+    if cmd_names:
+      print '\n%d command names:\n ' % len(cmd_names), '\n  '.join(cmd_names)
+
+    branches = d.get_sorted_branches()
+    if branches and (len(branches) > 1 or branches[0] != run_kind.branch):
+      print '\n%d branches:\n ' % len(branches), '\n  '.join(branches)
+
+    revisions = d.get_sorted_revisions()
+    if revisions and (len(revisions) > 1 or revisions[0] != run_kind.revision):
+      print '\n%d revisions:\n ' % len(revisions), '\n  '.join(revisions)
+
+    levels_spread = d.get_sorted_levels_spread()
+    if levels_spread and (
+         len(levels_spread) > 1
+         or levels_spread[0] != (run_kind.levels, run_kind.spread)):
+      print '\n%d kinds of levels x spread:\n ' % len(levels_spread), '\n  '.join(
+              [ ('%dx%d' % (l, s)) for l,s in levels_spread ])
 
+    print "\n%d runs in %d batches.\n" % (d.count_runs_batches())
 
-def cmdline_show(db, options, *run_kind_strings):
-  for run_kind_str in run_kind_strings:
-    run_kind = RunKind(run_kind_str)
 
+def cmdline_show(db, options, *run_kind_strings):
+  run_kinds = parse_timings_selections(db, *run_kind_strings)
+  for run_kind in run_kinds:
     q = TimingQuery(db, run_kind)
     timings = q.get_timings()
 
     s = []
-    s.append('Timings for %s' % run_kind.label)
+    s.append('Timings for %s' % run_kind.label())
     s.append('   N    min     max     avg   operation  (unit is seconds)')
 
     for command_name in q.get_sorted_command_names():
@@ -909,96 +986,108 @@ def cmdline_show(db, options, *run_kind_
     print '\n'.join(s)
 
 
-def cmdline_compare(db, options, left_str, right_str):
-  left_kind = RunKind(left_str)
-  right_kind = RunKind(right_str)
+def cmdline_compare(db, options, *args):
+  run_kinds = parse_timings_selections(db, *args)
+  if len(run_kinds) < 2:
+    bail("Need at least two sets of timings to compare.")
+
 
+  left_kind = run_kinds[0]
   leftq = TimingQuery(db, left_kind)
   left = leftq.get_timings()
   if not left:
-    print "No timings for", left_kind.label
-    exit(1)
+    bail("No timings for %s" % left_kind.label())
 
-  rightq = TimingQuery(db, right_kind)
-  right = rightq.get_timings()
-  if not right:
-    print "No timings for", right_kind.label
-    exit(1)
-
-  label = 'Compare %s to %s' % (left_kind.label, right_kind.label)
-
-  s = [label]
-
-  verbose = options.verbose
-  if not verbose:
-    s.append('       N        avg         operation')
-  else:
-    s.append('       N        min              max              avg         operation')
+  for run_kind_idx in range(1, len(run_kinds)):
+    right_kind = run_kinds[run_kind_idx]
 
-  command_names = [name for name in leftq.get_sorted_command_names()
-                   if name in right]
-  if options.command_names:
-    command_names = [name for name in command_names
-                     if name in options.command_names]
+    rightq = TimingQuery(db, right_kind)
+    right = rightq.get_timings()
+    if not right:
+      print "No timings for %s" % right_kind.label()
+      continue
 
-  for command_name in command_names:
-    left_N, left_min, left_max, left_avg = left[command_name]
-    right_N, right_min, right_max, right_avg = right[command_name]
-
-    N_str = '%s/%s' % (n_label(left_N), n_label(right_N))
-    avg_str = '%7.2f|%+7.3f' % (do_div(left_avg, right_avg),
-                                do_diff(left_avg, right_avg))
+    label = 'Compare %s to %s' % (right_kind.label(), left_kind.label())
 
+    s = [label]
+
+    verbose = options.verbose
     if not verbose:
-      s.append('%9s %-16s  %s' % (N_str, avg_str, command_name))
+      s.append('       N        avg         operation')
     else:
-      min_str = '%7.2f|%+7.3f' % (do_div(left_min, right_min),
-                                  do_diff(left_min, right_min))
-      max_str = '%7.2f|%+7.3f' % (do_div(left_max, right_max),
-                                  do_diff(left_max, right_max))
-
-      s.append('%9s %-16s %-16s %-16s  %s' % (N_str, min_str, max_str, avg_str,
-                                          command_name))
-
-  s.extend([
-    '(legend: "1.23|+0.45" means: slower by factor 1.23 and by 0.45 seconds;',
-    ' factor < 1 and seconds < 0 means \'%s\' is faster.'
-    % right_kind.label,
-    ' "2/3" means: \'%s\' has 2 timings on record, the other has 3.)'
-    % left_kind.label
-    ])
+      s.append('       N        min              max              avg         operation')
 
+    command_names = [name for name in leftq.get_sorted_command_names()
+                     if name in right]
+    if options.command_names:
+      command_names = [name for name in command_names
+                       if name in options.command_names]
 
-  print '\n'.join(s)
+    for command_name in command_names:
+      left_N, left_min, left_max, left_avg = left[command_name]
+      right_N, right_min, right_max, right_avg = right[command_name]
+
+      N_str = '%s/%s' % (n_label(left_N), n_label(right_N))
+      avg_str = '%7.2f|%+7.3f' % (do_div(left_avg, right_avg),
+                                  do_diff(left_avg, right_avg))
+
+      if not verbose:
+        s.append('%9s %-16s  %s' % (N_str, avg_str, command_name))
+      else:
+        min_str = '%7.2f|%+7.3f' % (do_div(left_min, right_min),
+                                    do_diff(left_min, right_min))
+        max_str = '%7.2f|%+7.3f' % (do_div(left_max, right_max),
+                                    do_diff(left_max, right_max))
+
+        s.append('%9s %-16s %-16s %-16s  %s' % (N_str, min_str, max_str, avg_str,
+                                            command_name))
+
+    s.extend([
+      '(legend: "1.23|+0.45" means: slower by factor 1.23 and by 0.45 seconds;',
+      ' factor < 1 and seconds < 0 means \'%s\' is faster.'
+      % right_kind.label(),
+      ' "2/3" means: \'%s\' has 2 timings on record, the other has 3.)'
+      % left_kind.label()
+      ])
+
+
+    print '\n'.join(s)
 
 
 # ------------------------------------------------------- charts
 
 def cmdline_chart_compare(db, options, *args):
+  import matplotlib
+  matplotlib.use('Agg')
   import numpy as np
-  import matplotlib.pyplot as plt
+  import matplotlib.pylab as plt
 
   labels = []
   timing_sets = []
   command_names = None
 
-  for arg in args:
-    run_kind = RunKind(arg)
+  run_kinds = parse_timings_selections(db, *args)
+
+  # iterate the timings selections and accumulate data
+  for run_kind in run_kinds:
     query = TimingQuery(db, run_kind)
     timings = query.get_timings()
     if not timings:
-      print "No timings for", run_kind.label
-      exit(1)
-    labels.append(run_kind.label)
+      print "No timings for %s" % run_kind.label()
+      continue
+    labels.append(run_kind.label())
     timing_sets.append(timings)
 
-    if command_names:
-      for i in range(len(command_names)):
-        if not command_names[i] in timings:
-          del command_names[i]
-    else:
+    # it only makes sense to compare those commands that have timings
+    # in the first selection, because that is the one everything else
+    # is compared to. Remember the first selection's command names.
+    if not command_names:
       command_names = query.get_sorted_command_names()
 
+
+  if len(timing_sets) < 2:
+    bail("Not enough timings")
+
   if options.command_names:
     command_names = [name for name in command_names
                      if name in options.command_names]
@@ -1009,99 +1098,125 @@ def cmdline_chart_compare(db, options, *
       [ filesystem_safe_string(l) for l in labels ]
       ) + '.svg'
                   
-  print '\nwriting chart file:', chart_path
-
   N = len(command_names)
   M = len(timing_sets) - 1
+  if M < 2:
+    M = 2
 
-  ind = np.arange(N)  # the x locations for the groups
-  width = 1. / (1.2 + M)     # the width of the bars
-  dist = 0.15
-
-  fig = plt.figure(figsize=(0.33*N*M,12))
-  plot1 = fig.add_subplot(211)
-  plot2 = fig.add_subplot(212)
-
-  # invisible lines that make sure the scale doesn't get minuscule
-  plot1.axhline(y=101, color='white', linewidth=0.01)
-  plot1.axhline(y=95.0, color='white', linewidth=0.01)
-  plot2.axhline(y=0.1, color='white', linewidth=0.01)
-  plot2.axhline(y=-0.5, color='white', linewidth=0.01)
-
-  reference = timing_sets[0]
-
-  ofs = 0
-
-  for label_i in range(1, len(labels)):
-    timings = timing_sets[label_i]
-    divs = []
-    diffs = []
-    divs_color = []
-    deviations = []
-    for command_name in command_names:
-      ref_N, ref_min, ref_max, ref_avg = reference[command_name]
-      this_N, this_min, this_max, this_avg = timings[command_name]
+  group_positions = np.arange(N)  # the y locations for the groups
+  dist = 1. / (1. + M)
+  height = (1. - dist) / M     # the height of the bars
+
+  fig = plt.figure(figsize=(12, 5 + 0.2*N*M))
+  plot1 = fig.add_subplot(121)
+  plot2 = fig.add_subplot(122)
+
+  left = timing_sets[0]
+
+  # Iterate timing sets. Each loop produces one bar for each command name
+  # group.
+  for label_i,label in enumerate(labels[1:],1):
+    right = timing_sets[label_i]
+    if not right:
+      continue
+
+    for cmd_i, command_name in enumerate(command_names):
+      if command_name not in right:
+        #skip
+        continue
+
+      left_N, left_min, left_max, left_avg = left[command_name]
+      right_N, right_min, right_max, right_avg = right[command_name]
 
-      val = 100. * (do_div(ref_avg, this_avg) - 1.0)
-      if val < 0:
+      div_avg = 100. * (do_div(left_avg, right_avg) - 1.0)
+      if div_avg <= 0:
         col = '#55dd55'
       else:
         col = '#dd5555'
-      divs.append(val)
-      divs_color.append(col)
-      diffs.append( do_diff(ref_avg, this_avg) )
-      deviations.append(this_max / this_min)
-
-    rects = plot1.bar(ind + ofs, divs, width * (1.0 - dist),
-                      color=divs_color, bottom=100.0, edgecolor='none')
-
-    for i in range(len(rects)):
-      x = rects[i].get_x() + width / 2.2
-      div = divs[i]
-      label = labels[label_i]
-
-      plot1.text(x, 100.,
-                 ' %+5.1f%% %s' % (div,label),
-                 ha='center', va='top', size='small',
-                 rotation=-90, family='monospace')
-
-    rects = plot2.bar(ind + ofs, diffs, width * 0.9,
-                   color=divs_color, bottom=0.0, edgecolor='none')
-
-    for i in range(len(rects)):
-      x = rects[i].get_x() + width / 2.2
-      diff = diffs[i]
-      label = labels[label_i]
-
-      plot2.text(x, 0.,
-                 ' %+5.2fs %s' % (diff,label),
-                 ha='center', va='top', size='small',
-                 rotation=-90, family='monospace')
-
-    ofs += width
-
-  plot1.set_title('Speed change compared to %s [%%]' % labels[0])
-  plot1.set_xticks(ind + (width / 2.))
-  plot1.set_xticklabels(command_names, rotation=-55,
-                        horizontalalignment='left',
-                        size='x-small', weight='bold')
-  plot1.axhline(y=100.0, color='#555555', linewidth=0.2)
-  plot2.set_title('[seconds]')
-  plot2.set_xticks(ind + (width / 2.))
-  plot2.set_xticklabels(command_names, rotation=-55,
-                        horizontalalignment='left',
-                        size='medium', weight='bold')
-  plot2.axhline(y=0.0, color='#555555', linewidth=0.2)
-
-  margin = 1.5/(N*M)
-  fig.subplots_adjust(bottom=0.1, top=0.97,
-                      left=margin,
-                      right=1.0-(margin / 2.))
 
-  #plot1.legend( (rects1[0], rects2[0]), (left_label, right_label) )
+      diff_val = do_diff(left_avg, right_avg)
+
+      ofs = (dist + height) / 2. + height * (label_i - 1)
+
+      barheight = height * (1.0 - dist)
+
+      y = float(cmd_i) + ofs
+
+      plot1.barh((y, ),
+                 (div_avg, ),
+                 barheight,
+                 color=col, edgecolor='white')
+      plot1.text(0., y + height/2.,
+                 '%s %+5.1f%%' % (label, div_avg),
+                 ha='right', va='center', size='small',
+                 rotation=0, family='monospace')
+
+      plot2.barh((y, ),
+                 (diff_val, ),
+                 barheight,
+                 color=col, edgecolor='white')
+      plot2.text(0., y + height/2.,
+                 '%s %+6.2fs' % (label, diff_val),
+                 ha='right', va='center', size='small',
+                 rotation=0, family='monospace')
+
+
+  for p in (plot1, plot2):
+    xlim = list(p.get_xlim())
+    if xlim[1] < 10.:
+      xlim[1] = 10.
+    # make sure the zero line is far enough right so that the annotations
+    # fit inside the chart. About half the width should suffice.
+    if xlim[0] > -xlim[1]:
+      xlim[0] = -xlim[1]
+    p.set_xlim(*xlim)
+    p.set_xticks((0,))
+    p.set_yticks(group_positions + (height / 2.))
+    p.set_yticklabels(())
+    p.set_ylim((len(command_names), 0))
+    p.grid()
+
+  plot1.set_xticklabels(('+-0%',), rotation=0)
+  plot1.set_title('Average runtime change from %s in %%' % labels[0],
+                  size='medium')
+
+  plot2.set_xticklabels(('+-0s',), rotation=0)
+  plot2.set_title('Average runtime change from %s in seconds' % labels[0],
+                  size='medium')
+
+  margin = 1./(2 + N*M)
+  titlemargin = 0
+  if options.title:
+    titlemargin = margin * 1.5
+
+  fig.subplots_adjust(left=0.005, right=0.995, wspace=0.3, bottom=margin,
+                      top=1.0-margin-titlemargin)
+
+  ystep = (1.0 - 2.*margin - titlemargin) / len(command_names)
+
+  for idx,command_name in enumerate(command_names):
+    ylabel = '%s\nvs. %.1fs' % (
+                     command_name,
+                     left[command_name][3])
+
+    ypos=1.0 - margin - titlemargin - ystep/M - ystep * idx
+    plt.figtext(0.5, ypos,
+                command_name,
+                ha='center', va='top',
+                size='medium', weight='bold')
+    plt.figtext(0.5, ypos - ystep/(M+1),
+                '%s\n= %.2fs' % (
+                  labels[0], left[command_name][3]),
+                ha='center', va='top',
+                size='small')
+
+  if options.title:
+    plt.figtext(0.5, 1. - titlemargin/2, options.title, ha='center',
+                va='center', weight='bold')
 
-  #plt.show()
   plt.savefig(chart_path)
+  print 'wrote chart file:', chart_path
+
 
 # ------------------------------------------------------------ main
 
@@ -1142,6 +1257,9 @@ if __name__ == '__main__':
   parser.add_option('-c', '--command-names', action='store',
                     dest='command_names',
                     help='Comma separated list of command names to limit to.')
+  parser.add_option('-t', '--title', action='store',
+                    dest='title',
+                    help='For charts, a title to print in the chart graphics.')
 
   parser.set_description(__doc__)
   parser.set_usage('')
@@ -1154,7 +1272,7 @@ if __name__ == '__main__':
     if msg:
       print
       print msg
-    exit(1)
+    bail()
 
   # there should be at least one arg left: the sub-command
   if not args:

Modified: subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/cronjob
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/cronjob?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/cronjob (original)
+++ subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/cronjob Sat Nov 24 20:29:11 2012
@@ -30,13 +30,7 @@
 # what it does: http://hofmeyr.de/pat/
 
 #EMAILS=your@ema.il add@ress.es
-EMAILS=""
-
-if [ "$USER" = "neels" ]; then
-  # I don't want to keep editing files after every update. ~Neels
-  EMAILS=dev@subversion.apache.org
-fi
-
+EMAILS=dev@subversion.apache.org
 
 echo
 echo "--------------------------------------------------------------------"
@@ -45,12 +39,16 @@ echo
 
 results="$(tempfile)"
 
+benchdir=/home/neels/svnbench
+patbin=/home/neels/bin/pat
+patbase=/home/neels/pat
+
 
 # first update trunk to HEAD and rebuild.
 # update/build is logged to the cronjob log (via stdout)
 
-cd /home/neels/pat/trunk
-/home/neels/bin/pat update
+cd "$patbase/trunk"
+"$patbin" update
 
 if [ "$?" -ne "0" ]; then
   subject="Failed to update to HEAD."
@@ -58,14 +56,14 @@ if [ "$?" -ne "0" ]; then
   echo "$subject"
 else
 
-  rev="$(/home/neels/pat/stable/prefix/bin/svn info /home/neels/pat/trunk/src | grep Revision)"
+  rev="$("$patbase"/stable/prefix/bin/svn info "$patbase"/trunk/src | grep Revision)"
   if [ -z "$rev" ]; then
     subject="Working copy problem."
     echo "$subject" > "$results"
     echo "$subject"
   else
 
-    NONMAINTAINER=1 /home/neels/bin/pat remake
+    NONMAINTAINER=1 "$patbin" remake
     if [ "$?" -ne "0" ]; then
       subject="Failed to build $rev."
       echo "$subject" > "$results"
@@ -76,10 +74,10 @@ else
       # updating and building succeeded!
       # run the benchmark:
 
-      compiled="$(/home/neels/pat/trunk/prefix/bin/svn --version | grep "compiled")"
+      compiled="$("$patbase"/trunk/prefix/bin/svn --version | grep "compiled")"
       subject="$rev$compiled"
 
-      cd /home/neels/svnbench/
+      cd "$benchdir"
 
       # make more or less sure that runs don't leak into each other via
       # I/O caching.
@@ -88,8 +86,8 @@ else
       # basically, just run it. But also, I want to
       # - append output to stdout, for cronjob logging.
       # - send output as mail, but only this run's output less update&build
-      "$(which time)" -p ./run 2>&1 | tee "$results"
-
+      time -p ./run 2>&1 | tee "$results"
+      time -p ./generate_charts 2>&1 | tee -a "$results"
     fi
   fi
 fi

Added: subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/generate_charts
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/generate_charts?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/generate_charts (added)
+++ subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/generate_charts Sat Nov 24 20:29:11 2012
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SVN_A_NAME="1.7.0"
+SVN_B_NAME="trunk"
+
+# benchmark script and parameters...
+benchmark="$PWD/benchmark.py"
+
+db="$PWD/${SVNBENCH_DEBUG}benchmark.db"
+
+chartsdir="$PWD/charts"
+
+mkdir -p "$chartsdir/.busy"
+
+if [ ! -e "$chartsdir/README" ]; then
+  cat > "$chartsdir/README" <<END
+These charts are generated by svn benchmark suite1.
+http://svn.apache.org/repos/asf/subversion/trunk/tools/dev/benchmarks/suite1
+
+*DISCLAIMER* - This tests only file://-URL access on a GNU/Linux VM.
+This is intended to measure changes in performance of the local working
+copy layer, *only*. These results are *not* generally true for everyone.
+END
+fi
+
+for levelspread in "" 5x5 1x100 100x1; do
+  if [ -z "$levelspread" ]; then
+    lsarg=""
+    lstitle=""
+  else
+    lsarg=",$levelspread"
+    lstitle=", WC dir levels x spread = $levelspread"
+  fi
+  N=12
+  "$benchmark" -f "$db" chart compare \
+     ${SVN_A_NAME}$lsarg ${SVN_B_NAME}@last${N}$lsarg \
+     -o "$chartsdir/.busy/compare_${SVN_A_NAME}_${SVN_B_NAME}@last${N}$lsarg.svg" \
+     -t "svn client benchmarks, file:// access *only*$lstitle"
+done
+
+mv "$chartsdir/.busy/"*.svg "$chartsdir/"
+rmdir "$chartsdir/.busy"
+

Modified: subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/run
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/run?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/run (original)
+++ subversion/branches/compressed-pristines/tools/dev/benchmarks/suite1/run Sat Nov 24 20:29:11 2012
@@ -88,9 +88,11 @@ started="$(date)"
 echo "Started at $started"
 
 echo "
-*Disclaimer* - This tests only file://-URL access on a GNU/Linux VM.
+*DISCLAIMER* - This tests only file://-URL access on a GNU/Linux VM.
 This is intended to measure changes in performance of the local working
-copy layer, *only*. These results are *not* generally true for everyone."
+copy layer, *only*. These results are *not* generally true for everyone.
+
+Charts of this data are available at http://svn-qavm.apache.org/charts/"
 
 if [ -z "$SVNBENCH_SUMMARY_ONLY" ]; then
   batch $al $as $N
@@ -139,6 +141,5 @@ done
 echo ""
 echo "Had started at $started,"
 echo "       done at $(date)"
-pwd
 } 2>&1 | tee results.txt
 

Modified: subversion/branches/compressed-pristines/tools/dev/svnraisetreeconflict/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dev/svnraisetreeconflict/main.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dev/svnraisetreeconflict/main.c (original)
+++ subversion/branches/compressed-pristines/tools/dev/svnraisetreeconflict/main.c Sat Nov 24 20:29:11 2012
@@ -218,10 +218,10 @@ raise_tree_conflict(int argc, const char
 
   /* Allocate and fill in the description data structures */
   SVN_ERR(svn_dirent_get_absolute(&wc_abspath, wc_path, pool));
-  left = svn_wc_conflict_version_create(repos_url1, path_in_repos1, peg_rev1,
-                                        kind1, pool);
-  right = svn_wc_conflict_version_create(repos_url2, path_in_repos2, peg_rev2,
-                                         kind2, pool);
+  left = svn_wc_conflict_version_create2(repos_url1, NULL, path_in_repos1,
+                                         peg_rev1, kind1, pool);
+  right = svn_wc_conflict_version_create2(repos_url2, NULL, path_in_repos2,
+                                          peg_rev2, kind2, pool);
   c = svn_wc_conflict_description_create_tree2(wc_abspath, kind,
                                               operation, left, right, pool);
   c->action = (svn_wc_conflict_action_t)action;

Modified: subversion/branches/compressed-pristines/tools/dev/unix-build/Makefile.svn
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dev/unix-build/Makefile.svn?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dev/unix-build/Makefile.svn (original)
+++ subversion/branches/compressed-pristines/tools/dev/unix-build/Makefile.svn Sat Nov 24 20:29:11 2012
@@ -862,6 +862,8 @@ endif
 		> $(CYRUS_SASL_SRCDIR)/lib/dlopen.c.patched
 	mv $(CYRUS_SASL_SRCDIR)/lib/dlopen.c.patched \
 		$(CYRUS_SASL_SRCDIR)/lib/dlopen.c
+	# Fix a weird autotools error about missing cmulocal dir
+	(cd $(CYRUS_SASL_SRCDIR)/saslauthd/ && ln -sf ../cmulocal)
 	touch $@
 
 # configure cyrus-sasl
@@ -961,6 +963,12 @@ $(RUBY_OBJDIR)/.retrieved: $(DISTDIR)/$(
 	tar -C $(SRCDIR) -zxf $(DISTDIR)/$(RUBY_DIST)
 	touch $@
 
+ifeq ($(THREADING),yes)
+THREADSAFE_FLAG=--enable-pthread
+else
+THREADSAFE_FLAG=--disable-pthread
+endif
+
 # configure ruby
 $(RUBY_OBJDIR)/.configured: $(RUBY_OBJDIR)/.retrieved
 	cd $(RUBY_OBJDIR) \
@@ -968,7 +976,7 @@ $(RUBY_OBJDIR)/.configured: $(RUBY_OBJDI
 		$(RUBY_SRCDIR)/configure \
 		--prefix=$(PREFIX)/ruby \
 		--enable-shared \
-		--disable-pthread
+		$(THREADSAFE_FLAG)
 	touch $@
 
 # compile ruby
@@ -1149,6 +1157,7 @@ MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_sv
 MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so
 LIBMAGIC_FLAG=--with-libmagic=$(PREFIX)/libmagic
 NEON_FLAG=--with-neon="$(PREFIX)/neon"
+JAVAHL_CHECK_TARGET=check-javahl
 else ifeq ($(BRANCH_MAJOR),1.6)
 BDB_FLAG=db.h:$(PREFIX)/bdb/include:$(PREFIX)/bdb/lib:db-$(BDB_MAJOR_VER)
 SERF_FLAG=--with-serf="$(PREFIX)/serf"
@@ -1156,6 +1165,7 @@ MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_sv
 MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so
 W_NO_SYSTEM_HEADERS=-Wno-system-headers
 NEON_FLAG=--with-neon="$(PREFIX)/neon"
+JAVAHL_CHECK_TARGET=check-javahl
 else ifeq ($(BRANCH_MAJOR),1.5)
 BDB_FLAG=$(PREFIX)/bdb
 SERF_FLAG=--with-serf="$(PREFIX)/serf-old"
@@ -1164,12 +1174,14 @@ MOD_AUTHZ_SVN=modules/mod_authz_svn.so
 DISABLE_NEON_VERSION_CHECK=--disable-neon-version-check
 W_NO_SYSTEM_HEADERS=-Wno-system-headers
 NEON_FLAG=--with-neon="$(PREFIX)/neon"
+JAVAHL_CHECK_TARGET=check-javahl
 else # 1.8
 BDB_FLAG=db.h:$(PREFIX)/bdb/include:$(PREFIX)/bdb/lib:db-$(BDB_MAJOR_VER)
 SERF_FLAG=--with-serf="$(PREFIX)/serf"
 MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_svn.so
 MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so
 LIBMAGIC_FLAG=--with-libmagic=$(PREFIX)/libmagic
+JAVAHL_CHECK_TARGET=check-all-javahl
 endif
 
 ifeq ($(ENABLE_JAVA_BINDINGS),yes)
@@ -1350,10 +1362,17 @@ endif
 libpath:
 	@echo export LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$$LD_LIBRARY_PATH" \
 		"PYTHONPATH=$(SVN_PREFIX)/lib/svn-python"
+#
+# OpenBSD requires an LD_PRELOAD hack to dlopen() libraries linked to
+# libpthread (e.g. libsvn_auth_gnome_keyring.so) into executables that
+# aren't linked to libpthread.
+ifeq ($(UNAME),OpenBSD)
+LIB_PTHREAD_HACK=LD_PRELOAD=libpthread.so
+endif
 
 .PHONY: start-svnserve stop-svnserve start-httpd stop-httpd
 
-HTTPD_CMD = env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
+HTTPD_CMD = env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(LIB_PTHREAD_HACK) \
 		$(PREFIX)/httpd/bin/apachectl -f $(HTTPD_CHECK_CONF)
 HTTPD_START_CMD = $(HTTPD_CMD) -k start
 HTTPD_START_CMD_DEBUG = $(HTTPD_START_CMD) -X
@@ -1400,7 +1419,7 @@ define do_check
 -cd $(svn_builddir) && for fs in fsfs bdb; do \
     echo "Begin test: $(subst svn-check-,,$@) x $$fs"; \
     test -d "$(RAMDISK)/tmp" && export TMPDIR="$(RAMDISK)/tmp"; \
-    env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
+    env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(LIB_PTHREAD_HACK) \
         make check PARALLEL=$(PARALLEL) CLEANUP=$(CLEANUP) $1 FS_TYPE=$$fs; \
     for log in tests.log fails.log; do \
         test -f $$log && mv -f $$log $$log.$@-$$fs; \
@@ -1456,6 +1475,7 @@ svn-check-swig-pl:
 	-if [ $(ENABLE_PERL_BINDINGS) = yes ]; then \
 		(cd $(svn_builddir) && \
 			env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
+			$(LIB_PTHREAD_HACK) \
 			make check-swig-pl 2>&1) | \
 				tee $(svn_builddir)/tests.log.bindings.pl; \
 	fi
@@ -1473,6 +1493,7 @@ svn-check-swig-rb:
 		env RUBYLIB=$(RUBYLIB) \
 		LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
 		PATH=$(SVN_PREFIX)/bin:$$PATH \
+		$(LIB_PTHREAD_HACK) \
 			make check-swig-rb 2>&1) | \
 			tee $(svn_builddir)/tests.log.bindings.rb
 
@@ -1480,7 +1501,7 @@ svn-check-javahl:
 	-if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \
 		(cd $(svn_builddir) && \
 			env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \
-			make check-all-javahl 2>&1) | \
+			make $(JAVAHL_CHECK_TARGET) 2>&1) | \
 				tee $(svn_builddir)/tests.log.bindings.javahl; \
 	fi
 

Modified: subversion/branches/compressed-pristines/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dist/backport.pl?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dist/backport.pl (original)
+++ subversion/branches/compressed-pristines/tools/dist/backport.pl Sat Nov 24 20:29:11 2012
@@ -126,9 +126,9 @@ EOF
 reinteg_rev=\`$SVN info $STATUS | sed -ne 's/Last Changed Rev: //p'\`
 if $WET_RUN; then
   # Sleep to avoid out-of-order commit notifications
-  if [ -n "$YES" ]; then sleep 15; fi
+  if [ -n "\$YES" ]; then sleep 15; fi
   $SVNq rm $BRANCHES/$entry{branch} -m "Remove the '$entry{branch}' branch, reintegrated in r\$reinteg_rev."
-  if [ -n "$YES" ]; then sleep 1; fi
+  if [ -n "\$YES" ]; then sleep 1; fi
 else
   echo "Removing reintegrated '$entry{branch}' branch"
 fi
@@ -229,6 +229,10 @@ sub main {
   usage, exit 0 if @ARGV;
   usage, exit 1 unless -r $STATUS;
 
+  # Because we use the ':normal' command in Vim...
+  die "A vim with the +ex_extra feature is required"
+      if `${VIM} --version` !~ /[+]ex_extra/;
+
   @ARGV = $STATUS;
 
   # Skip most of the file

Modified: subversion/branches/compressed-pristines/tools/dist/make-deps-tarball.sh
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dist/make-deps-tarball.sh?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dist/make-deps-tarball.sh (original)
+++ subversion/branches/compressed-pristines/tools/dist/make-deps-tarball.sh Sat Nov 24 20:29:11 2012
@@ -21,14 +21,12 @@
 #
 set -e
 
-# NOTE: Before bumping the default APR dependency the 1.6.x test suite
-# should be adjusted to cope with hash ordering changes from APR 1.4.6.
-APR=apr-1.4.5
+APR=apr-1.4.6
 APR_UTIL=apr-util-1.4.1
 NEON=neon-0.29.6
 SERF=serf-0.3.1
-ZLIB=zlib-1.2.6
-SQLITE_VERSION=3071100
+ZLIB=zlib-1.2.7
+SQLITE_VERSION=3071400
 SQLITE=sqlite-amalgamation-$SQLITE_VERSION
 
 HTTPD=httpd-2.2.22

Modified: subversion/branches/compressed-pristines/tools/dist/nightly.sh
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dist/nightly.sh?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dist/nightly.sh (original)
+++ subversion/branches/compressed-pristines/tools/dist/nightly.sh Sat Nov 24 20:29:11 2012
@@ -55,10 +55,10 @@ head=`$svn info $repo/trunk | grep '^Rev
 # Get the latest versions of the rolling scripts
 for i in release.py dist.sh
 do 
-  $svn export -r $head $repo/trunk/tools/dist/$i@$head $dir/$i
+  $svn export --force -r $head $repo/trunk/tools/dist/$i@$head $dir/$i
 done
 # We also need ezt
-$svn export -r $head $repo/trunk/build/generator/ezt.py@$head $dir/ezt.py
+$svn export --force -r $head $repo/trunk/build/generator/ezt.py@$head $dir/ezt.py
 
 # Create the environment
 cd roll

Modified: subversion/branches/compressed-pristines/tools/dist/release.py
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/dist/release.py?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/tools/dist/release.py (original)
+++ subversion/branches/compressed-pristines/tools/dist/release.py Sat Nov 24 20:29:11 2012
@@ -679,7 +679,7 @@ def write_downloads(args):
 #----------------------------------------------------------------------
 # Validate the signatures for a release
 
-key_start = '-----BEGIN PGP SIGNATURE-----\n'
+key_start = '-----BEGIN PGP SIGNATURE-----'
 fp_pattern = re.compile(r'^pub\s+(\w+\/\w+)[^\n]*\n\s+Key\sfingerprint\s=((\s+[0-9A-F]{4}){10})\nuid\s+([^<\(]+)\s')
 
 def check_sigs(args):

Added: subversion/branches/compressed-pristines/tools/hook-scripts/persist-ephemeral-txnprops.py
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/tools/hook-scripts/persist-ephemeral-txnprops.py?rev=1413258&view=auto
==============================================================================
--- subversion/branches/compressed-pristines/tools/hook-scripts/persist-ephemeral-txnprops.py (added)
+++ subversion/branches/compressed-pristines/tools/hook-scripts/persist-ephemeral-txnprops.py Sat Nov 24 20:29:11 2012
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+
+import sys
+import os
+from svn import repos, fs, core
+
+def duplicate_ephemeral_txnprops(repos_path, txn_name):
+  fs_ptr = repos.fs(repos.open(repos_path))
+  txn_t = fs.open_txn(fs_ptr, txn_name)
+  for name, value in fs.txn_proplist(txn_t).items():
+    if name.startswith(core.SVN_PROP_TXN_PREFIX):
+      name = core.SVN_PROP_REVISION_PREFIX + \
+                  name[len(core.SVN_PROP_TXN_PREFIX):]
+      fs.change_txn_prop(txn_t, name, value)
+
+def usage_and_exit(errmsg=None):
+  stream = errmsg and sys.stderr or sys.stdout
+  stream.write("""\
+Usage:
+
+   persist-ephemeral-txnprops.py REPOS_PATH TXN_NAME
+
+Duplicate ephemeral transaction properties so that the information
+they carry may persist as properties of the revision created once the
+transaction is committed.  This is intended to be used as a Subversion
+pre-commit hook script.
+
+REPOS_PATH is the on-disk path of the repository whose transaction
+properties are being examined/modified.  TXN_NAME is the name of the
+transaction.
+
+Ephemeral transaction properties, whose names all begin with the
+prefix "%s", will be copied to new properties which use the
+prefix "%s" instead.
+
+""" % (core.SVN_PROP_TXN_PREFIX, core.SVN_PROP_REVISION_PREFIX))
+  if errmsg:
+    stream.write("ERROR: " + errmsg + "\n")
+  sys.exit(errmsg and 1 or 0)
+
+def main():
+  argc = len(sys.argv)
+  if argc != 3:
+    usage_and_exit("Incorrect number of arguments.")
+  repos_path = sys.argv[1]
+  txn_name = sys.argv[2]
+  duplicate_ephemeral_txnprops(repos_path, txn_name)
+
+if __name__ == "__main__":
+  main()



Mime
View raw message