subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cmpil...@apache.org
Subject svn commit: r896142 [2/3] - in /subversion/branches/issue-3242-dev: ./ build/ build/ac-macros/ build/generator/templates/ notes/tree-conflicts/ subversion/bindings/ctypes-python/test/ subversion/bindings/javahl/tests/org/tigris/subversion/javahl/ subve...
Date Tue, 05 Jan 2010 17:32:11 GMT
Modified: subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.c Tue Jan  5 17:31:58 2010
@@ -49,6 +49,8 @@
 #include "bdb/reps-table.h"
 #include "bdb/strings-table.h"
 #include "bdb/checksum-reps-table.h"
+#include "bdb/changes-table.h"
+#include "bdb/node-origins-table.h"
 
 #include "private/svn_skel.h"
 #include "private/svn_fs_util.h"
@@ -1625,21 +1627,157 @@
                                    &date, trail, pool);
 }
 
+/* Modify all entries in the "node-origins" table that have a txn-id of
+ * OLD_TXN_ID to refer to NEW_TXN_ID instead.
+ *
+ * Work within TRAIL. */
+static svn_error_t *
+node_origins_update(const char *new_txn_id,
+                    const char *old_txn_id,
+                    trail_t *trail,
+                    apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *changes;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  int i;
+
+  /* To find the nodes that originate in the old txn, we'll look in the
+   * "changes" table. Any change that added a node could have created a new
+   * node id. */
+  SVN_ERR(svn_fs_bdb__changes_fetch_raw(&changes, trail->fs, old_txn_id, trail,
+                                        scratch_pool));
+  for (i = 0; i < changes->nelts; i++)
+    {
+      change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
+
+      svn_pool_clear(iterpool);
+
+      if (change->kind == svn_fs_path_change_add
+          || change->kind == svn_fs_path_change_replace)
+        {
+          const svn_fs_id_t *origin_id;
+          const char *node_id, *id_copy_id, *id_txn_id;
+
+          /* Find the destination node id of this change */
+          node_id = svn_fs_base__id_node_id(change->noderev_id);
+
+          /* Fetch the old node-origin */
+          SVN_ERR(svn_fs_bdb__get_node_origin(&origin_id, trail->fs, node_id,
+                                              trail, iterpool));
+          id_copy_id = svn_fs_base__id_copy_id(origin_id);
+          id_txn_id = svn_fs_base__id_txn_id(origin_id);
+
+          if (svn_fs_base__key_compare(id_txn_id, old_txn_id) == 0)
+            {
+              /* Change its txn_id to NEW_TXN_ID */
+              origin_id = svn_fs_base__id_create(node_id, id_copy_id,
+                                                 new_txn_id, iterpool);
+              /* Save the new node-origin */
+              SVN_ERR(svn_fs_bdb__delete_node_origin(trail->fs, node_id, trail,
+                                                     iterpool));
+              SVN_ERR(svn_fs_bdb__set_node_origin(trail->fs, node_id,
+                                                  origin_id, trail,
+                                                  iterpool));
+            }
+        }
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+/* Modify each row in the "copies" table that is keyed by a (const char *)
+ * copy-id listed in COPY_IDS, changing the txn-id component of its
+ * "dst_noderev_id" field from OLD_TXN_ID to NEW_TXN_ID.
+ * Each entry in COPY_IDS must match exactly one row in the "copies" table.
+ *
+ * Work within TRAIL. */
+static svn_error_t *
+copies_update(const char *new_txn_id,
+              const char *old_txn_id,
+              apr_array_header_t *copy_ids,
+              trail_t *trail,
+              apr_pool_t *scratch_pool)
+{
+  int i;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  for (i = 0; i < copy_ids->nelts; i++)
+    {
+      const char *copy_id = APR_ARRAY_IDX(copy_ids, i, const char *);
+      copy_t *copy;
+      const char *id_node_id, *id_copy_id, *id_txn_id;
+
+      svn_pool_clear(iterpool);
+
+      /* Get the old "copy" row from the "copies" table */
+      SVN_ERR(svn_fs_bdb__get_copy(&copy, trail->fs, copy_id, trail,
+                                   iterpool));
+
+      /* Modify it: change dst_noderev_id's txn_id from old to new txn-id */
+      id_node_id = svn_fs_base__id_node_id(copy->dst_noderev_id);
+      id_copy_id = svn_fs_base__id_copy_id(copy->dst_noderev_id);
+      id_txn_id = svn_fs_base__id_txn_id(copy->dst_noderev_id);
+      SVN_ERR_ASSERT(svn_fs_base__key_compare(id_copy_id, copy_id) == 0);
+      SVN_ERR_ASSERT(svn_fs_base__key_compare(id_txn_id, old_txn_id) == 0);
+      copy->dst_noderev_id = svn_fs_base__id_create(id_node_id, id_copy_id,
+                                                    new_txn_id, iterpool);
+
+      /* Write the new "copy" row back under the same key (copy_id) */
+      SVN_ERR(svn_fs_bdb__create_copy(trail->fs, copy_id,
+                                      copy->src_path, copy->src_txn_id,
+                                      copy->dst_noderev_id, copy->kind,
+                                      trail, iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_base__dag_commit_obliteration_txn(svn_revnum_t replacing_rev,
                                          svn_fs_txn_t *txn,
                                          trail_t *trail,
-                                         apr_pool_t *pool)
+                                         apr_pool_t *scratch_pool)
 {
+  transaction_t *txn_obj;
   revision_t revision;
+  const char *old_txn_id;
+
+  /* Find the old txn. */
+  SVN_ERR(svn_fs_base__rev_get_txn_id(&old_txn_id, trail->fs, replacing_rev,
+                                      trail, scratch_pool));
+
+  /* Read the new txn so we can access its "copies" list */
+  SVN_ERR(svn_fs_bdb__get_txn(&txn_obj, trail->fs, txn->id, trail,
+                              scratch_pool));
+
+  /* Finish updating the "copies" table, which was started in
+   * svn_fs_base__begin_obliteration_txn().  Change the keys of all the
+   * "copies" table rows that we created back to their original keys.
+   *
+   * This assumes that the old 'replacing_rev' transaction is now obsolete,
+   * so that the old "copies" table rows are no longer referenced.
+   *
+   * ### TODO: See txn_body_begin_obliteration_txn().
+   * ### TODO: Guarantee the old txn is obsolete.
+   */
+  if (txn_obj->copies)
+    SVN_ERR(copies_update(txn->id, old_txn_id, txn_obj->copies, trail,
+                          scratch_pool));
 
   /* Replace the revision entry in the `revisions' table. */
   revision.txn_id = txn->id;
-  SVN_ERR(svn_fs_bdb__put_rev(&replacing_rev, txn->fs, &revision, trail, pool));
+  SVN_ERR(svn_fs_bdb__put_rev(&replacing_rev, txn->fs, &revision, trail,
+                              scratch_pool));
 
   /* Promote the unfinished transaction to a committed one. */
   SVN_ERR(svn_fs_base__txn_make_committed(txn->fs, txn->id, replacing_rev,
-                                          trail, pool));
+                                          trail, scratch_pool));
+
+  /* Update the "node-origins" table. */
+  SVN_ERR(node_origins_update(txn->id, old_txn_id, trail, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.h?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.h (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/dag.h Tue Jan  5 17:31:58 2010
@@ -289,7 +289,7 @@
 svn_fs_base__dag_commit_obliteration_txn(svn_revnum_t replacing_rev,
                                          svn_fs_txn_t *txn,
                                          trail_t *trail,
-                                         apr_pool_t *pool);
+                                         apr_pool_t *scratch_pool);
 
 
 

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/obliterate.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/obliterate.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/obliterate.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/obliterate.c Tue Jan  5 17:31:58 2010
@@ -187,8 +187,9 @@
     }
   else if (noderev->kind == svn_node_file)
     {
-      SVN_ERR(svn_fs_base__rep_dup(&noderev->data_key, new_txn_id,
-                                   noderev->data_key, trail, scratch_pool));
+      if (noderev->data_key)
+        SVN_ERR(svn_fs_base__rep_dup(&noderev->data_key, new_txn_id,
+                                     noderev->data_key, trail, scratch_pool));
 
       SVN_ERR(svn_fs_bdb__put_node_revision(trail->fs, *new_id, noderev, trail,
                                             scratch_pool));

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/revs-txns.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/revs-txns.c Tue Jan  5 17:31:58 2010
@@ -437,9 +437,9 @@
 /* Duplicate all entries in the "changes" table that are keyed by OLD_TXN_ID,
  * creating new entries that are keyed by NEW_TXN_ID.
  *
- * Each new "change" has the same content as the old one, except with the
- * txn-id component of its noderev-id (which is assumed to have been
- * OLD_TXN_ID) changed to NEW_TXN_ID.
+ * Each new "change" has the same content as the old one, except that if the
+ * txn-id component of its noderev-id is OLD_TXN_ID (which is the case for
+ * all changes except deletes) then that is changed to NEW_TXN_ID.
  *
  * Work within TRAIL. */
 static svn_error_t *
@@ -824,18 +824,30 @@
   /* Dup txn->proplist */
   new_txn->proplist = old_txn->proplist;
 
-  /* ### TODO: Update "copies" table entries referenced by txn->copies.
-   * This is hard, because I don't want to change the copy_ids, because they
-   * pervade node-ids throughout history. But what actually uses them, and
-   * does anything use them during txn construction? */
+  /* Prepare to update the "copies" table.
+   *
+   * As part of obliteration, we need to update all of the "copies" table
+   * rows that are referenced by this txn, to refer to the new txn's
+   * node-rev ids instead. At txn begin time, just keep the references to
+   * the old rows. At commit time, we will update those rows to refer to
+   * this txn's node-rev ids.
+   *
+   * We cannot simply create new "copies" table rows now and make the old
+   * ones obsolete at commit time, because the rows are keyed by copy-id,
+   * and we don't want to change the copy_ids because they pervade node-ids
+   * throughout history.
+   *
+   * ### What actually uses the "copies" table? Does anything use it during
+   * txn construction? Does it need to be keyed by copy-id or could we
+   * change the schema to use arbitrary keys? */
+  if (old_txn->copies)
+    {
+      new_txn->copies = apr_array_copy(trail->pool, old_txn->copies);
+    }
 
   /* Dup the "changes" that are keyed by the txn_id. */
   SVN_ERR(changes_dup(new_txn_id, old_txn_id, trail, trail->pool));
 
-  /* ### TODO: Update the "node-origins" table.
-   * Or can this be deferred till commit time? Probably not. */
-
-
   /* Save the modified transaction */
   SVN_ERR(svn_fs_bdb__put_txn(trail->fs, new_txn, new_txn_id, trail,
                               trail->pool));

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/trail.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/trail.h?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/trail.h (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_fs_base/trail.h Tue Jan  5 17:31:58 2010
@@ -119,7 +119,29 @@
    SVN_NO_ERROR, `svn_fs_base__retry_txn' commits the trail's Berkeley DB
    transaction, thus making your DB changes permanent, leaves the
    trail's pool alone so all the objects it contains are still
-   around (unless you request otherwise), and returns SVN_NO_ERROR.  */
+   around (unless you request otherwise), and returns SVN_NO_ERROR.
+
+
+   Keep the amount of work done in a trail small. C-Mike Pilato said to me:
+
+   I want to draw your attention to something that you may or may not realize
+   about designing for the BDB backend.  The 'trail' objects are (generally)
+   representative of Berkeley DB transactions -- that part I'm sure you know.
+   But you might not realize the value of keeping transactions as small as
+   possible.  Berkeley DB will accumulate locks (which I believe are
+   page-level, not as tight as row-level like you might hope) over the course
+   of a transaction, releasing those locks only at transaction commit/abort.
+   Berkeley DB backends are configured to have a maximum number of locks and
+   lockers allowed, and it's easier than you might think to hit the max-locks
+   thresholds (especially under high concurrency) and see an error (typically a
+   "Cannot allocate memory") result from that.
+
+   For example, in [a loop] you are writing a bunch of rows to the
+   `changes' table.  Could be 10.  Could be 100,000.  100,000 writes and
+   associated locks might be a problem or it might not.  But I use it as a way
+   to encourage you to think about reducing the amount of work you spend in any
+   one trail [...].
+*/
 
 struct trail_t
 {

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_fs_fs/fs_fs.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_fs_fs/fs_fs.c Tue Jan  5 17:31:58 2010
@@ -34,6 +34,7 @@
 #include <apr_lib.h>
 #include <apr_md5.h>
 #include <apr_sha1.h>
+#include <apr_strings.h>
 #include <apr_thread_mutex.h>
 
 #include "svn_pools.h"
@@ -457,8 +458,7 @@
     }
 
   assert(strlen(txn_id) < sizeof(txn->txn_id));
-  strncpy(txn->txn_id, txn_id, sizeof(txn->txn_id) - 1);
-  txn->txn_id[sizeof(txn->txn_id) - 1] = '\0';
+  apr_cpystrn(txn->txn_id, txn_id, sizeof(txn->txn_id));
   txn->being_written = FALSE;
 
   /* Link this transaction into the head of the list.  We will typically
@@ -6641,14 +6641,12 @@
       if (svn_fs_fs__key_compare(node_id, max_node_id) > 0)
         {
           assert(strlen(node_id) < MAX_KEY_SIZE);
-          strncpy(max_node_id, node_id, MAX_KEY_SIZE - 1);
-          max_node_id[MAX_KEY_SIZE - 1] = '\0';
+          apr_cpystrn(max_node_id, node_id, MAX_KEY_SIZE);
         }
       if (svn_fs_fs__key_compare(copy_id, max_copy_id) > 0)
         {
           assert(strlen(copy_id) < MAX_KEY_SIZE);
-          strncpy(max_copy_id, copy_id, MAX_KEY_SIZE - 1);
-          max_copy_id[MAX_KEY_SIZE - 1] = '\0';
+          apr_cpystrn(max_copy_id, copy_id, MAX_KEY_SIZE);
         }
 
       if (kind == svn_node_file)

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/auth.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/auth.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/auth.c Tue Jan  5 17:31:58 2010
@@ -33,6 +33,7 @@
 
 /*** Forward declarations. ***/
 
+#if ! SERF_VERSION_AT_LEAST(0, 4, 0)
 static svn_error_t *
 handle_basic_auth(svn_ra_serf__handler_t *ctx,
                   serf_request_t *request,
@@ -51,6 +52,7 @@
                          const char *method,
                          const char *uri,
                          serf_bucket_t *hdrs_bkt);
+#endif
 
 static svn_error_t *
 handle_proxy_basic_auth(svn_ra_serf__handler_t *ctx,
@@ -82,6 +84,8 @@
 
 /*** Global variables. ***/
 static const svn_ra_serf__auth_protocol_t serf_auth_protocols[] = {
+#if ! SERF_VERSION_AT_LEAST(0, 4, 0)
+  /* serf handles Basic authentication. */
   {
     401,
     "Basic",
@@ -100,6 +104,7 @@
     setup_request_proxy_basic_auth,
     default_auth_response_handler,
   },
+#endif
 #ifdef SVN_RA_SERF_SSPI_ENABLED
   {
     401,
@@ -120,6 +125,7 @@
     default_auth_response_handler,
   },
 #endif /* SVN_RA_SERF_SSPI_ENABLED */
+#if ! SERF_VERSION_AT_LEAST(0, 4, 0)
   {
     401,
     "Digest",
@@ -129,6 +135,7 @@
     svn_ra_serf__setup_request_digest_auth,
     svn_ra_serf__validate_response_digest_auth,
   },
+#endif
 #ifdef SVN_RA_SERF_HAVE_GSSAPI
   {
     401,
@@ -356,6 +363,7 @@
   return SVN_NO_ERROR;
 }
 
+#if ! SERF_VERSION_AT_LEAST(0, 4, 0)
 static svn_error_t *
 handle_basic_auth(svn_ra_serf__handler_t *ctx,
                   serf_request_t *request,
@@ -496,6 +504,7 @@
 
   return SVN_NO_ERROR;
 }
+#endif
 
 static svn_error_t *
 handle_proxy_basic_auth(svn_ra_serf__handler_t *ctx,

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/ra_serf.h?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/ra_serf.h Tue Jan  5 17:31:58 2010
@@ -1402,6 +1402,16 @@
 /*** Authentication handler declarations ***/
 
 /**
+ * Callback function that loads the credentials for Basic and Digest
+ * authentications, both for server and proxy authentication.
+ */
+apr_status_t
+svn_ra_serf__credentials_callback(char **username, char **password,
+                                  serf_request_t *request, void *baton,
+                                  int code, const char *authn_type,
+                                  const char *realm,
+                                  apr_pool_t *pool);
+/**
  * For each authentication protocol we need a handler function of type
  * svn_serf__auth_handler_func_t. This function will be called when an
  * authentication challenge is received in a session.

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/serf.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/serf.c Tue Jan  5 17:31:58 2010
@@ -303,9 +303,15 @@
   else
     session->using_proxy = FALSE;
 
-  /* Load the list of support authn types. */
-   SVN_ERR(load_http_auth_types(pool, config, server_group,
-           &session->authn_types));
+  /* Setup authentication. */
+  SVN_ERR(load_http_auth_types(pool, config, server_group,
+                               &session->authn_types));
+#if SERF_VERSION_AT_LEAST(0, 4, 0)
+  /* TODO: convert string authn types to SERF_AUTHN bitmask.
+     serf_config_authn_types(session->context, session->authn_types);*/
+  serf_config_credentials_callback(session->context,
+                                   svn_ra_serf__credentials_callback);
+#endif
 
   return SVN_NO_ERROR;
 }
@@ -360,14 +366,12 @@
      older, for root paths url.path will be "", where serf requires "/". */
   if (url.path == NULL || url.path[0] == '\0')
     url.path = apr_pstrdup(serf_sess->pool, "/");
-
-  serf_sess->repos_url = url;
-  serf_sess->repos_url_str = apr_pstrdup(serf_sess->pool, repos_URL);
-
   if (!url.port)
     {
       url.port = apr_uri_port_of_scheme(url.scheme);
     }
+  serf_sess->repos_url = url;
+  serf_sess->repos_url_str = apr_pstrdup(serf_sess->pool, repos_URL);
   serf_sess->using_ssl = (svn_cstring_casecmp(url.scheme, "https") == 0);
 
   serf_sess->capabilities = apr_hash_make(serf_sess->pool);
@@ -430,11 +434,15 @@
     serf_sess->conns[0]->useragent = USER_AGENT;
 
   /* go ahead and tell serf about the connection. */
-  serf_sess->conns[0]->conn =
-      serf_connection_create(serf_sess->context, serf_sess->conns[0]->address,
-                             svn_ra_serf__conn_setup, serf_sess->conns[0],
-                             svn_ra_serf__conn_closed, serf_sess->conns[0],
-                             serf_sess->pool);
+  status =
+    serf_connection_create2(&serf_sess->conns[0]->conn,
+                            serf_sess->context,
+                            url,
+                            svn_ra_serf__conn_setup, serf_sess->conns[0],
+                            svn_ra_serf__conn_closed, serf_sess->conns[0],
+                            serf_sess->pool);
+  if (status)
+    return svn_error_wrap_apr(status, NULL);
 
   /* Set the progress callback. */
   serf_context_set_progress_cb(serf_sess->context, svn_ra_serf__progress,

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/update.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/update.c Tue Jan  5 17:31:58 2010
@@ -2127,7 +2127,7 @@
  * if the number of ACTIVE_REQS > REQS_PER_CONN or if there currently is
  * only one main connection open.
  */
-static void
+static svn_error_t *
 open_connection_if_needed(svn_ra_serf__session_t *sess, int active_reqs)
 {
   /* For each REQS_PER_CONN outstanding requests open a new connection, with
@@ -2136,6 +2136,7 @@
       ((active_reqs / REQS_PER_CONN) > sess->num_conns))
     {
       int cur = sess->num_conns;
+      apr_status_t status;
 
       sess->conns[cur] = apr_palloc(sess->pool, sizeof(*sess->conns[cur]));
       sess->conns[cur]->bkt_alloc = serf_bucket_allocator_create(sess->pool,
@@ -2150,13 +2151,17 @@
       sess->conns[cur]->last_status_code = -1;
       sess->conns[cur]->ssl_context = NULL;
       sess->conns[cur]->session = sess;
-      sess->conns[cur]->conn = serf_connection_create(sess->context,
-                                                      sess->conns[cur]->address,
-                                                      svn_ra_serf__conn_setup,
-                                                      sess->conns[cur],
-                                                      svn_ra_serf__conn_closed,
-                                                      sess->conns[cur],
-                                                      sess->pool);
+      status = serf_connection_create2(&sess->conns[cur]->conn,
+                                       sess->context,
+                                       sess->repos_url,
+                                       svn_ra_serf__conn_setup,
+                                       sess->conns[cur],
+                                       svn_ra_serf__conn_closed,
+                                       sess->conns[cur],
+                                       sess->pool);
+      if (status)
+        return svn_error_wrap_apr(status, NULL);
+
       sess->num_conns++;
 
       /* Authentication protocol specific initalization. */
@@ -2166,6 +2171,8 @@
         sess->proxy_auth_protocol->init_conn_func(sess, sess->conns[cur],
                                                   sess->pool);
     }
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -2220,7 +2227,7 @@
   svn_ra_serf__request_create(handler);
 
   /* Open the first extra connection. */
-  open_connection_if_needed(sess, 0);
+  SVN_ERR(open_connection_if_needed(sess, 0));
 
   sess->cur_conn = 1;
   closed_root = FALSE;
@@ -2244,8 +2251,8 @@
 
       /* Open extra connections if we have enough requests to send. */
       if (sess->num_conns < MAX_NR_OF_CONNS)
-        open_connection_if_needed(sess, report->active_fetches +
-                                        report->active_propfinds);
+        SVN_ERR(open_connection_if_needed(sess, report->active_fetches +
+                                          report->active_propfinds));
 
       /* Switch our connection. */
       if (!report->done)

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/util.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_ra_serf/util.c Tue Jan  5 17:31:58 2010
@@ -504,8 +504,9 @@
 {
   serf_bucket_t *hdrs_bkt;
 
-  *req_bkt = serf_bucket_request_create(method, url, body_bkt,
-                                        serf_request_get_alloc(request));
+  *req_bkt =
+    serf_request_bucket_request_create(request, method, url, body_bkt,
+                                       serf_request_get_alloc(request));
 
   hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
   serf_bucket_headers_setn(hdrs_bkt, "Host", conn->hostinfo);
@@ -553,15 +554,6 @@
     }
 #endif
 
-  /* Set up Proxy settings */
-  if (conn->session->using_proxy)
-    {
-      char *root = apr_uri_unparse(conn->session->pool,
-                                   &conn->session->repos_url,
-                                   APR_URI_UNP_OMITPATHINFO);
-      serf_bucket_request_set_root(*req_bkt, root);
-    }
-
   if (ret_hdrs_bkt)
     {
       *ret_hdrs_bkt = hdrs_bkt;
@@ -1179,6 +1171,85 @@
   return server_err.error;
 }
 
+apr_status_t
+svn_ra_serf__credentials_callback(char **username, char **password,
+                                  serf_request_t *request, void *baton,
+                                  int code, const char *authn_type,
+                                  const char *realm,
+                                  apr_pool_t *pool)
+{
+  svn_ra_serf__handler_t *ctx = baton;
+  svn_ra_serf__session_t *session = ctx->session;
+  void *creds;
+  svn_auth_cred_simple_t *simple_creds;
+  svn_error_t *err;
+
+  if (code == 401)
+    {
+      /* Use svn_auth_first_credentials if this is the first time we ask for
+         credentials during this session OR if the last time we asked
+         session->auth_state wasn't set (eg. if the credentials provider was
+         cancelled by the user). */
+      if (!session->auth_state)
+        {
+          err = svn_auth_first_credentials(&creds,
+                                           &session->auth_state,
+                                           SVN_AUTH_CRED_SIMPLE,
+                                           realm,
+                                           session->wc_callbacks->auth_baton,
+                                           session->pool);
+        }
+      else
+        {
+          err = svn_auth_next_credentials(&creds,
+                                          session->auth_state,
+                                          session->pool);
+        }
+
+      if (err)
+        {
+          ctx->session->pending_error = err;
+          return err->apr_err;
+        }
+
+      session->auth_attempts++;
+
+      if (!creds || session->auth_attempts > 4)
+        {
+          /* No more credentials. */
+          ctx->session->pending_error =
+            svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+                             "No more credentials or we tried too many times.\n"
+                             "Authentication failed");
+          return SVN_ERR_AUTHN_FAILED;
+        }
+
+      simple_creds = creds;
+      *username = apr_pstrdup(pool, simple_creds->username);
+      *password = apr_pstrdup(pool, simple_creds->password);
+    }
+  else
+    {
+      *username = apr_pstrdup(pool, session->proxy_username);
+      *password = apr_pstrdup(pool, session->proxy_password);
+
+      session->proxy_auth_attempts++;
+
+      if (!session->proxy_username || session->proxy_auth_attempts > 4)
+        {
+          /* No more credentials. */
+          ctx->session->pending_error =
+            svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+                             "Proxy authentication failed");
+          return SVN_ERR_AUTHN_FAILED;
+        }
+    }
+
+  ctx->conn->last_status_code = code;
+
+  return APR_SUCCESS;
+}
+
 /* Implements the serf_response_handler_t interface.  Wait for HTTP
    response status and headers, and invoke CTX->response_handler() to
    carry out operation-specific processing.  Afterwards, check for

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_repos/obliterate.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_repos/obliterate.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_repos/obliterate.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_repos/obliterate.c Tue Jan  5 17:31:58 2010
@@ -42,7 +42,7 @@
                                apr_pool_t *pool)
 {
   svn_fs_t *fs = svn_repos_fs(repos);
-  svn_fs_root_t *rev_root;
+  svn_fs_root_t *rev_root, *txn_root;
   svn_fs_txn_t *txn;
   const svn_fs_id_t *node_id;
 
@@ -62,9 +62,10 @@
 
   /* Begin a new transaction, based on the revision we want to modify. */
   SVN_ERR(svn_fs__begin_obliteration_txn(&txn, fs, revision, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
 
   /* Make the required changes in this txn */
-  /* ... */
+  SVN_ERR(svn_fs_delete(txn_root, path, pool));
 
   /* Commit the new transaction in place of the old revision */
   SVN_ERR(svn_fs__commit_obliteration_txn(revision, txn, pool));

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_subr/mergeinfo.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_subr/mergeinfo.c Tue Jan  5 17:31:58 2010
@@ -655,8 +655,8 @@
      leading slash, e.g. "trunk:4033\n/trunk:4039-4995".  In the event
      we encounter this we merge the rangelists together under a single
      absolute path key. */
-  if (existing_rangelist = apr_hash_get(hash, pathname->data,
-                                        APR_HASH_KEY_STRING))
+  existing_rangelist = apr_hash_get(hash, pathname->data, APR_HASH_KEY_STRING);
+  if (existing_rangelist)
     svn_rangelist_merge(&rangelist, existing_rangelist, pool);
 
   apr_hash_set(hash, pathname->data, APR_HASH_KEY_STRING, rangelist);

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_subr/opt.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_subr/opt.c Tue Jan  5 17:31:58 2010
@@ -1004,7 +1004,7 @@
   SVN_ERR(svn_cmdline_printf(pool, _("%s, version %s\n"
                                      "   compiled %s, %s\n\n"), pgm_name,
                              SVN_VERSION, __DATE__, __TIME__));
-  SVN_ERR(svn_cmdline_fputs(_("Copyright (C) 2009 The Apache Software Foundation.\n"
+  SVN_ERR(svn_cmdline_fputs(_("Copyright (C) 2010 The Apache Software Foundation.\n"
                               "This software consists of"
                               " contributions made by many people;\n"
                               "see the NOTICE file for more information.\n"

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_subr/stream.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_subr/stream.c Tue Jan  5 17:31:58 2010
@@ -42,6 +42,7 @@
 #include "svn_utf.h"
 #include "svn_checksum.h"
 #include "svn_path.h"
+#include "private/svn_eol_private.h"
 
 
 struct svn_stream_t {
@@ -50,10 +51,19 @@
   svn_write_fn_t write_fn;
   svn_close_fn_t close_fn;
   svn_io_reset_fn_t reset_fn;
+  svn_io_mark_fn_t mark_fn;
+  svn_io_seek_fn_t seek_fn;
   svn_io_line_filter_cb_t line_filter_cb;
   svn_io_line_transformer_cb_t line_transformer_cb;
 };
 
+/* A type which represents a mark on a stream. */
+struct svn_stream_mark_t {
+  union {
+    apr_off_t apr;
+    apr_size_t stringbuf;
+  } m;
+};
 
 
 /*** Generic streams. ***/
@@ -67,8 +77,10 @@
   stream->baton = baton;
   stream->read_fn = NULL;
   stream->write_fn = NULL;
-  stream->reset_fn = NULL;
   stream->close_fn = NULL;
+  stream->reset_fn = NULL;
+  stream->mark_fn = NULL;
+  stream->seek_fn = NULL;
   stream->line_filter_cb = NULL;
   stream->line_transformer_cb = NULL;
   return stream;
@@ -96,15 +108,27 @@
 }
 
 void
+svn_stream_set_close(svn_stream_t *stream, svn_close_fn_t close_fn)
+{
+  stream->close_fn = close_fn;
+}
+
+void
 svn_stream_set_reset(svn_stream_t *stream, svn_io_reset_fn_t reset_fn)
 {
   stream->reset_fn = reset_fn;
 }
 
 void
-svn_stream_set_close(svn_stream_t *stream, svn_close_fn_t close_fn)
+svn_stream_set_mark(svn_stream_t *stream, svn_io_mark_fn_t mark_fn)
 {
-  stream->close_fn = close_fn;
+  stream->mark_fn = mark_fn;
+}
+
+void
+svn_stream_set_seek(svn_stream_t *stream, svn_io_seek_fn_t seek_fn)
+{
+  stream->seek_fn = seek_fn;
 }
 
 void
@@ -147,6 +171,24 @@
   return stream->reset_fn(stream->baton);
 }
 
+svn_error_t *
+svn_stream_mark(svn_stream_t *stream, svn_stream_mark_t **mark,
+                apr_pool_t *pool)
+{
+  if (stream->mark_fn == NULL)
+    return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED, NULL, NULL);
+
+  return stream->mark_fn(stream->baton, mark, pool);
+}
+
+svn_error_t *
+svn_stream_seek(svn_stream_t *stream, svn_stream_mark_t *mark)
+{
+  if (stream->seek_fn == NULL)
+    return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED, NULL, NULL);
+
+  return stream->seek_fn(stream->baton, mark);
+}
 
 svn_error_t *
 svn_stream_close(svn_stream_t *stream)
@@ -238,16 +280,55 @@
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_stream_readline(svn_stream_t *stream,
-                    svn_stringbuf_t **stringbuf,
-                    const char *eol,
-                    svn_boolean_t *eof,
-                    apr_pool_t *pool)
+/* Scan STREAM for an end-of-line indicatior, and return it in *EOL.
+ * Set *EOL to NULL if the stream runs out before an end-of-line indicator
+ * is found. */
+static svn_error_t *
+scan_eol(const char **eol, svn_stream_t *stream, apr_pool_t *pool)
+{
+  const char *eol_str;
+  svn_stream_mark_t *mark;
+
+  SVN_ERR(svn_stream_mark(stream, &mark, pool));
+
+  eol_str = NULL;
+  while (! eol_str)
+    {
+      char buf[512];
+      apr_size_t len;
+
+      len = sizeof(buf);
+      SVN_ERR(svn_stream_read(stream, buf, &len));
+      if (len == 0)
+          break; /* EOF */
+      eol_str = svn_eol__detect_eol(buf, buf + len);
+    }
+
+  SVN_ERR(svn_stream_seek(stream, mark));
+
+  *eol = eol_str;
+
+  return SVN_NO_ERROR;
+}
+
+/* Guts of svn_stream_readline() and svn_stream_readline_detect_eol().
+ * Returns the line read from STREAM in *STRINGBUF, and indicates
+ * end-of-file in *EOF.  If DETECT_EOL is TRUE, the end-of-line indicator
+ * is detected automatically and returned in *EOL.
+ * If DETECT_EOL is FALSE, *EOL must point to the desired end-of-line
+ * indicator.  STRINGBUF is allocated in POOL. */
+static svn_error_t *
+stream_readline(svn_stringbuf_t **stringbuf,
+                svn_boolean_t *eof,
+                const char **eol,
+                svn_stream_t *stream,
+                svn_boolean_t detect_eol,
+                apr_pool_t *pool)
 {
   svn_stringbuf_t *str;
   apr_pool_t *iterpool;
   svn_boolean_t filtered;
+  const char *eol_str;
 
   *eof = FALSE;
 
@@ -266,8 +347,22 @@
          80 chars.  */
       str = svn_stringbuf_create_ensure(80, iterpool);
 
+      if (detect_eol)
+        {
+          SVN_ERR(scan_eol(&eol_str, stream, iterpool));
+          if (eol)
+            *eol = eol_str;
+          if (! eol_str)
+            {
+              /* No newline until EOF, EOL_STR can be anything. */
+              eol_str = APR_EOL_STR;
+            }
+        }
+      else
+        eol_str = *eol;
+
       /* Read into STR up to and including the next EOL sequence. */
-      match = eol;
+      match = eol_str;
       while (*match)
         {
           numbytes = 1;
@@ -278,7 +373,7 @@
               *eof = TRUE;
               /* We know we don't have a whole EOL sequence, but ensure we
                * don't chop off any partial EOL sequence that we may have. */
-              match = eol;
+              match = eol_str;
               /* Process this short (or empty) line just like any other
                * except with *EOF set. */
               break;
@@ -287,12 +382,12 @@
           if (c == *match)
             match++;
           else
-            match = eol;
+            match = eol_str;
 
           svn_stringbuf_appendbytes(str, &c, 1);
         }
 
-      svn_stringbuf_chop(str, match - eol);
+      svn_stringbuf_chop(str, match - eol_str);
 
       SVN_ERR(line_filter(stream, &filtered, str->data, iterpool));
     }
@@ -313,6 +408,28 @@
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_stream_readline(svn_stream_t *stream,
+                    svn_stringbuf_t **stringbuf,
+                    const char *eol,
+                    svn_boolean_t *eof,
+                    apr_pool_t *pool)
+{
+  return svn_error_return(stream_readline(stringbuf, eof, &eol, stream,
+                                          FALSE, pool));
+}
+
+svn_error_t *
+svn_stream_readline_detect_eol(svn_stream_t *stream,
+                               svn_stringbuf_t **stringbuf,
+                               const char **eol,
+                               svn_boolean_t *eof,
+                               apr_pool_t *pool)
+{
+  return svn_error_return(stream_readline(stringbuf, eof, eol, stream,
+                                          TRUE, pool));
+}
+
 
 svn_error_t *svn_stream_copy3(svn_stream_t *from, svn_stream_t *to,
                               svn_cancel_func_t cancel_func,
@@ -407,6 +524,18 @@
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+mark_handler_empty(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+seek_handler_empty(void *baton, svn_stream_mark_t *mark)
+{
+  return SVN_NO_ERROR;
+}
+
 
 svn_stream_t *
 svn_stream_empty(apr_pool_t *pool)
@@ -417,6 +546,8 @@
   svn_stream_set_read(stream, read_handler_empty);
   svn_stream_set_write(stream, write_handler_empty);
   svn_stream_set_reset(stream, reset_handler_empty);
+  svn_stream_set_mark(stream, mark_handler_empty);
+  svn_stream_set_seek(stream, seek_handler_empty);
   return stream;
 }
 
@@ -499,6 +630,17 @@
   return svn_stream_reset(baton);
 }
 
+static svn_error_t *
+mark_handler_disown(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
+{
+  return svn_stream_mark(baton, mark, pool);
+}
+
+static svn_error_t *
+seek_handler_disown(void *baton, svn_stream_mark_t *mark)
+{
+  return svn_stream_seek(baton, mark);
+}
 
 svn_stream_t *
 svn_stream_disown(svn_stream_t *stream, apr_pool_t *pool)
@@ -508,6 +650,8 @@
   svn_stream_set_read(s, read_handler_disown);
   svn_stream_set_write(s, write_handler_disown);
   svn_stream_set_reset(s, reset_handler_disown);
+  svn_stream_set_mark(s, mark_handler_disown);
+  svn_stream_set_seek(s, seek_handler_disown);
 
   return s;
 }
@@ -571,7 +715,6 @@
   return err;
 }
 
-
 static svn_error_t *
 write_handler_apr(void *baton, const char *data, apr_size_t *len)
 {
@@ -581,6 +724,14 @@
 }
 
 static svn_error_t *
+close_handler_apr(void *baton)
+{
+  struct baton_apr *btn = baton;
+
+  return svn_io_file_close(btn->file, btn->pool);
+}
+
+static svn_error_t *
 reset_handler_apr(void *baton)
 {
   apr_off_t offset;
@@ -594,13 +745,22 @@
 }
 
 static svn_error_t *
-close_handler_apr(void *baton)
+mark_handler_apr(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
 {
   struct baton_apr *btn = baton;
-
-  return svn_io_file_close(btn->file, btn->pool);
+  (*mark) = apr_palloc(pool, sizeof(**mark));
+  (*mark)->m.apr = 0;
+  SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &(*mark)->m.apr, btn->pool));
+  return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+seek_handler_apr(void *baton, svn_stream_mark_t *mark)
+{
+  struct baton_apr *btn = baton;
+  SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &mark->m.apr, btn->pool));
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_stream_open_readonly(svn_stream_t **stream,
@@ -677,6 +837,8 @@
   svn_stream_set_read(stream, read_handler_apr);
   svn_stream_set_write(stream, write_handler_apr);
   svn_stream_set_reset(stream, reset_handler_apr);
+  svn_stream_set_mark(stream, mark_handler_apr);
+  svn_stream_set_seek(stream, seek_handler_apr);
 
   if (! disown)
     svn_stream_set_close(stream, close_handler_apr);
@@ -717,6 +879,8 @@
   stream = svn_stream_create(baton, pool);
   svn_stream_set_read(stream, read_handler_apr);
   svn_stream_set_reset(stream, reset_handler_apr);
+  svn_stream_set_mark(stream, mark_handler_apr);
+  svn_stream_set_seek(stream, seek_handler_apr);
 
   if (! disown)
     svn_stream_set_close(stream, close_handler_apr);
@@ -1245,6 +1409,23 @@
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+mark_handler_stringbuf(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
+{
+  struct stringbuf_stream_baton *btn = baton;
+  (*mark) = apr_palloc(pool, sizeof(**mark));
+  (*mark)->m.stringbuf = btn->amt_read;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+seek_handler_stringbuf(void *baton, svn_stream_mark_t *mark)
+{
+  struct stringbuf_stream_baton *btn = baton;
+  btn->amt_read = mark->m.stringbuf;
+  return SVN_NO_ERROR;
+}
+
 svn_stream_t *
 svn_stream_from_stringbuf(svn_stringbuf_t *str,
                           apr_pool_t *pool)
@@ -1262,6 +1443,8 @@
   svn_stream_set_read(stream, read_handler_stringbuf);
   svn_stream_set_write(stream, write_handler_stringbuf);
   svn_stream_set_reset(stream, reset_handler_stringbuf);
+  svn_stream_set_mark(stream, mark_handler_stringbuf);
+  svn_stream_set_seek(stream, seek_handler_stringbuf);
   return stream;
 }
 

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/adm_crawler.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/adm_crawler.c Tue Jan  5 17:31:58 2010
@@ -396,7 +396,7 @@
             {
               /* Report the excluded path, no matter whether report_everything
                  flag is set.  Because the report_everything flag indicates
-                 that the server will treate the wc as empty and thus push
+                 that the server will treat the wc as empty and thus push
                  full content of the files/subdirs. But we want to prevent the
                  server from pushing the full content of this_path at us. */
 

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/entries.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/entries.c Tue Jan  5 17:31:58 2010
@@ -1568,29 +1568,25 @@
 
       if (entry != NULL)
         {
+          /* The entries in the parent stub only store excluded vs infinity. */
           entry->depth = (depth == svn_depth_exclude) ? svn_depth_exclude
                                                       : svn_depth_infinity;
         }
     }
 
-  /* ### setting depth exclude on a wcroot breaks svn_wc_crop() */
-  if (depth != svn_depth_exclude)
+   /* Fetch the entries for the directory, and write our depth there. */
+  adm_access = svn_wc__adm_retrieve_internal2(db, local_dir_abspath,
+                                              scratch_pool);
+  if (adm_access != NULL)
     {
-       /* We aren't excluded, so fetch the entries for the directory, and write
-        our depth there. */
-      adm_access = svn_wc__adm_retrieve_internal2(db, local_dir_abspath,
-                                                  scratch_pool);
-      if (adm_access != NULL)
-        {
-          apr_hash_t *entries = svn_wc__adm_access_entries(adm_access);
+      apr_hash_t *entries = svn_wc__adm_access_entries(adm_access);
 
-          entry = (entries != NULL)
-                           ? apr_hash_get(entries, "", APR_HASH_KEY_STRING)
-                           : NULL;
+      entry = (entries != NULL)
+                       ? apr_hash_get(entries, "", APR_HASH_KEY_STRING)
+                       : NULL;
 
-          if (entry != NULL)
-            entry->depth = depth;
-        }
+      if (entry != NULL)
+        entry->depth = depth;
     }
 
   return svn_error_return(svn_wc__db_temp_op_set_dir_depth(db,

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/lock.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/lock.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/lock.c Tue Jan  5 17:31:58 2010
@@ -1734,12 +1734,12 @@
   apr_pool_t *iterpool;
   const apr_array_header_t *children;
   svn_boolean_t parent_is_anchor = FALSE;
-  int i;
+  int format, i;
+  svn_error_t *err;
 
   if (anchor_abspath)
     {
       const char *parent_abspath, *base;
-      svn_error_t *err;
 
       svn_dirent_split(local_abspath, &parent_abspath, &base, scratch_pool);
       err = svn_wc__db_read_children(&children, wc_ctx->db, parent_abspath,
@@ -1791,8 +1791,15 @@
                                            NULL, iterpool));
     }
 
-  SVN_ERR(svn_wc__db_wclock_set(wc_ctx->db, local_abspath, 0, iterpool));
-  SVN_ERR(svn_wc__db_temp_mark_locked(wc_ctx->db, local_abspath, iterpool));
+  /* We don't want to try and lock an unversioned directory that
+     obstructs a versioned directory. */
+  err = svn_wc__internal_check_wc(&format, wc_ctx->db, local_abspath, iterpool);
+  if (!err && format)
+    {
+      SVN_ERR(svn_wc__db_wclock_set(wc_ctx->db, local_abspath, 0, iterpool));
+      SVN_ERR(svn_wc__db_temp_mark_locked(wc_ctx->db, local_abspath, iterpool));
+    }
+  svn_error_clear(err);
 
   svn_pool_destroy(iterpool);
 

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/props.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/props.c Tue Jan  5 17:31:58 2010
@@ -2444,6 +2444,15 @@
       apr_hash_t *mergeinfo;
       svn_string_t *new_value_str;
 
+
+      /* Non-inheritable mergeinfo is only valid on directories. */
+      if (kind != svn_node_dir
+          && strstr(propval->data, SVN_MERGEINFO_NONINHERITABLE_STR))
+        return svn_error_createf(
+          SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
+          _("Cannot set non-inheritable mergeinfo on a non-directory ('%s')"),
+          svn_dirent_local_style(path, pool));
+
       SVN_ERR(svn_mergeinfo_parse(&mergeinfo, propval->data, pool));
       SVN_ERR(svn_mergeinfo_to_string(&new_value_str, mergeinfo, pool));
       new_value = svn_stringbuf_create_from_string(new_value_str, pool);

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/update_editor.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/update_editor.c Tue Jan  5 17:31:58 2010
@@ -4926,7 +4926,8 @@
   /* If we had a text change, drop the pristine into it's proper place. */
   if (fb->temp_pristine_abspath)
     SVN_ERR(svn_wc__db_pristine_install(eb->db, fb->temp_pristine_abspath,
-                                        sha1_actual_checksum, pool));
+                                        sha1_actual_checksum,
+                                        md5_actual_checksum, pool));
 #endif
 
   /* It's a small world, after all. */

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc-queries.sql?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc-queries.sql Tue Jan  5 17:31:58 2010
@@ -248,8 +248,8 @@
 DELETE FROM WORK_QUEUE WHERE id = ?1;
 
 -- STMT_INSERT_PRISTINE
-INSERT OR IGNORE INTO PRISTINE (checksum, size, refcount)
-VALUES (?1, ?2, 1);
+INSERT OR IGNORE INTO PRISTINE (checksum, md5_checksum, size, refcount)
+VALUES (?1, ?2, ?3, 1);
 
 -- STMT_SELECT_ACTUAL_CONFLICT_VICTIMS
 SELECT local_relpath

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.c Tue Jan  5 17:31:58 2010
@@ -2334,7 +2334,8 @@
 svn_error_t *
 svn_wc__db_pristine_install(svn_wc__db_t *db,
                             const char *tempfile_abspath,
-                            const svn_checksum_t *checksum,
+                            const svn_checksum_t *sha1_checksum,
+                            const svn_checksum_t *md5_checksum,
                             apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
@@ -2345,7 +2346,8 @@
   svn_sqlite__stmt_t *stmt;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
-  SVN_ERR_ASSERT(checksum != NULL);
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  SVN_ERR_ASSERT(md5_checksum != NULL);
 
   VERIFY_CHECKSUM_KIND(checksum);
 
@@ -2362,7 +2364,7 @@
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
-  SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, checksum,
+  SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
                              TRUE /* create_subdir */,
                              scratch_pool, scratch_pool));
 
@@ -2375,8 +2377,9 @@
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_INSERT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool));
-  SVN_ERR(svn_sqlite__bind_int64(stmt, 2, finfo.size));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
   return SVN_NO_ERROR;
@@ -3082,23 +3085,18 @@
   if (flush_entry_cache)
     flush_entries(pdh);
 
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_BASE_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
+  SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
+  SVN_ERR(svn_sqlite__step_done(stmt));
 
-  /* ### setting depth exclude on a wcroot breaks svn_wc_crop() */
-  if (strcmp(current_relpath, "") != 0 || depth != svn_depth_exclude)
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_BASE_DEPTH));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
-      SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_WORKING_DEPTH));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
-      SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_WORKING_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
+  SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
+  SVN_ERR(svn_sqlite__step_done(stmt));
 
   /* Check if we should also set depth in the parent db */
-  if (strcmp(current_relpath, "") == 0)
+  if (flush_entry_cache && strcmp(current_relpath, "") == 0)
     {
       svn_error_t *err;
 
@@ -3114,26 +3112,7 @@
       else
         SVN_ERR(err);
 
-      if (flush_entry_cache)
-        flush_entries(pdh);
-
-      depth = (depth == svn_depth_exclude) ? svn_depth_exclude
-                                           : svn_depth_infinity;
-
-      VERIFY_USABLE_PDH(pdh);
-      wcroot = pdh->wcroot;
-      sdb = wcroot->sdb;
-      current_relpath = svn_dirent_basename(local_abspath, NULL);
-
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_BASE_DEPTH));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
-      SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_WORKING_DEPTH));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
-      SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
-      SVN_ERR(svn_sqlite__step_done(stmt));
+      flush_entries(pdh);
     }
 
   return SVN_NO_ERROR;
@@ -5583,12 +5562,28 @@
                       int levels_to_lock,
                       apr_pool_t *scratch_pool)
 {
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
   svn_sqlite__stmt_t *stmt;
   svn_error_t *err;
 
-  SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
-                                 STMT_INSERT_WC_LOCK, scratch_pool));
-  SVN_ERR(svn_sqlite__bind_int64(stmt, 3, levels_to_lock));
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
+                              svn_sqlite__mode_readwrite,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  /* ### Can only lock this directory in the per-dir layout.  This is
+     ### a temporary restriction until metadata gets centralised.
+     ### Perhaps this should be a runtime error, rather than an
+     ### assert?  Perhaps check the path is versioned? */
+  SVN_ERR_ASSERT(*local_relpath == '\0');
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                    STMT_INSERT_WC_LOCK));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isi", pdh->wcroot->wc_id, local_relpath,
+                            levels_to_lock));
   err = svn_sqlite__insert(NULL, stmt);
   if (err)
     return svn_error_createf(SVN_ERR_WC_LOCKED, err,

Modified: subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.h?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/issue-3242-dev/subversion/libsvn_wc/wc_db.h Tue Jan  5 17:31:58 2010
@@ -827,11 +827,14 @@
    ### install the sucker into the pristine datastore for the given checksum.
    ### This is used for files where we don't know the checksum ahead of
    ### time, so we drop it into a temp area first, computing the checksum
-   ### as we write it there. */
+   ### as we write it there.
+   
+   ### the md5_checksum parameter is temporary. */
 svn_error_t *
 svn_wc__db_pristine_install(svn_wc__db_t *db,
                             const char *tempfile_abspath,
-                            const svn_checksum_t *checksum,
+                            const svn_checksum_t *sha1_checksum,
+                            const svn_checksum_t *md5_checksum,
                             apr_pool_t *scratch_pool);
 
 

Modified: subversion/branches/issue-3242-dev/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/mod_dav_svn/merge.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/mod_dav_svn/merge.c (original)
+++ subversion/branches/issue-3242-dev/subversion/mod_dav_svn/merge.c Tue Jan  5 17:31:58 2010
@@ -252,7 +252,9 @@
       post_commit_err_elem = apr_psprintf(pool,
                                           "<S:post-commit-err>%s"
                                           "</S:post-commit-err>",
-                                          post_commit_err);
+                                          apr_xml_quote_string(pool,
+                                                               post_commit_err,
+                                                               0));
     }
   else
     {

Modified: subversion/branches/issue-3242-dev/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/svn/cl.h?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/svn/cl.h (original)
+++ subversion/branches/issue-3242-dev/subversion/svn/cl.h Tue Jan  5 17:31:58 2010
@@ -136,9 +136,9 @@
   /* An array of svn_opt_revision_range_t *'s representing revisions
      ranges indicated on the command-line via the -r and -c options.
      For each range in the list, if only one revision was provided
-     (-rN), its 'end' member remains `svn_opt_revision_unspecified'.
-
-     NOTE: This is currently used only by merge subcommand. */
+     (-rN), its 'end' member remains 'svn_opt_revision_unspecified'.
+     This array always has at least one element, even if that is a
+     null range in which both ends are 'svn_opt_revision_unspecified'. */
   apr_array_header_t *revision_ranges;
 
   /* These are simply a copy of the range start and end values present
@@ -222,6 +222,7 @@
   svn_boolean_t trust_server_cert; /* trust server SSL certs that would
                                       otherwise be rejected as "untrusted" */
   int strip_count; /* number of leading path components to strip */
+  svn_boolean_t ignore_keywords;  /* do not expand keywords */
 } svn_cl__opt_state_t;
 
 

Modified: subversion/branches/issue-3242-dev/subversion/svn/export-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/svn/export-cmd.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/svn/export-cmd.c (original)
+++ subversion/branches/issue-3242-dev/subversion/svn/export-cmd.c Tue Jan  5 17:31:58 2010
@@ -91,12 +91,11 @@
     opt_state->depth = svn_depth_infinity;
 
   /* Do the export. */
-  err = svn_client_export4(NULL, truefrom, to, &peg_revision,
+  err = svn_client_export5(NULL, truefrom, to, &peg_revision,
                            &(opt_state->start_revision),
                            opt_state->force, opt_state->ignore_externals,
-                           opt_state->depth,
-                           opt_state->native_eol, ctx,
-                           pool);
+                           opt_state->ignore_keywords, opt_state->depth,
+                           opt_state->native_eol, ctx, pool);
   if (err && err->apr_err == SVN_ERR_WC_OBSTRUCTED_UPDATE && !opt_state->force)
     SVN_ERR_W(err,
               _("Destination directory exists; please remove "

Modified: subversion/branches/issue-3242-dev/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/svn/main.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/svn/main.c (original)
+++ subversion/branches/issue-3242-dev/subversion/svn/main.c Tue Jan  5 17:31:58 2010
@@ -114,7 +114,8 @@
   opt_show_revs,
   opt_reintegrate,
   opt_trust_server_cert,
-  opt_show_copies_as_adds
+  opt_show_copies_as_adds,
+  opt_ignore_keywords
 } svn_cl__longopt_t;
 
 /* Option codes and descriptions for the command line client.
@@ -309,6 +310,10 @@
                        "while -p2 would give just crunchy.html")},
   {"show-copies-as-adds", opt_show_copies_as_adds, 0,
                     N_("don't diff copied or moved files with their source")},
+  {"ignore-keywords", opt_ignore_keywords, 0,
+                    N_("don't expand keywords\n"
+                       "                             "
+                       "[aliases: --ik]")},
 
   /* Long-opt Aliases
    *
@@ -318,6 +323,7 @@
 
   {"cl",            opt_changelist, 1, NULL},
   {"ie",            opt_ignore_externals, 0, NULL},
+  {"ik",            opt_ignore_keywords, 0, NULL},
 
   {0,               0, 0, 0},
 };
@@ -514,7 +520,8 @@
      "\n"
      "  If specified, PEGREV determines in which revision the target is first\n"
      "  looked up.\n"),
-    {'r', 'q', 'N', opt_depth, opt_force, opt_native_eol, opt_ignore_externals} },
+    {'r', 'q', 'N', opt_depth, opt_force, opt_native_eol, opt_ignore_externals,
+     opt_ignore_keywords} },
 
   { "help", svn_cl__help, {"?", "h"}, N_
     ("Describe the usage of this program or its subcommands.\n"
@@ -1660,6 +1667,9 @@
             }
         }
         break;
+      case opt_ignore_keywords:
+        opt_state.ignore_keywords = TRUE;
+        break;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */
@@ -1776,7 +1786,7 @@
         }
     }
 
-  /* Only merge supports multiple revisions/revision ranges. */
+  /* Only merge and log support multiple revisions/revision ranges. */
   if (subcommand->cmd_func != svn_cl__merge
       && subcommand->cmd_func != svn_cl__log)
     {
@@ -1790,17 +1800,6 @@
         }
     }
 
-  /* Merge doesn't support specifying a revision range
-     when using --reintegrate. */
-  if (subcommand->cmd_func == svn_cl__merge
-      && opt_state.revision_ranges->nelts
-      && opt_state.reintegrate)
-    {
-      err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                             _("-r and -c can't be used with --reintegrate"));
-      return svn_cmdline_handle_exit_error(err, pool, "svn: ");
-    }
-
   /* Disallow simultaneous use of both --depth and --set-depth. */
   if ((opt_state.depth != svn_depth_unknown)
       && (opt_state.set_depth != svn_depth_unknown))
@@ -1840,7 +1839,7 @@
       return svn_cmdline_handle_exit_error(err, pool, "svn: ");
     }
 
-  /* Ensure that 'revision_ranges' has at least one item, and that
+  /* Ensure that 'revision_ranges' has at least one item, and make
      'start_revision' and 'end_revision' match that item. */
   if (opt_state.revision_ranges->nelts == 0)
     {

Modified: subversion/branches/issue-3242-dev/subversion/svn/merge-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/svn/merge-cmd.c?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/svn/merge-cmd.c (original)
+++ subversion/branches/issue-3242-dev/subversion/svn/merge-cmd.c Tue Jan  5 17:31:58 2010
@@ -56,6 +56,15 @@
     peg_revision2;
   apr_array_header_t *options, *ranges_to_merge = opt_state->revision_ranges;
 
+  /* Merge doesn't support specifying a revision or revision range
+     when using --reintegrate. */
+  if (opt_state->reintegrate
+      && opt_state->start_revision.kind != svn_opt_revision_unspecified)
+    {
+      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                              _("-r and -c can't be used with --reintegrate"));
+    }
+
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
                                                       ctx, pool));

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/basic_tests.py?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/basic_tests.py Tue Jan  5 17:31:58 2010
@@ -2491,8 +2491,7 @@
               basic_update,
               basic_mkdir_url,
               basic_mkdir_url_with_parents,
-              Wimp("currently, WC locks are being left behind",
-                   basic_mkdir_wc_with_parents),
+              basic_mkdir_wc_with_parents,
               basic_corruption,
               basic_merging_update,
               basic_conflict,

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/commit_tests.py?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/commit_tests.py Tue Jan  5 17:31:58 2010
@@ -2062,28 +2062,6 @@
                                      os.path.join(wc_dir, 'A', 'mu'),
                                      os.path.join(wc_dir, 'A', 'yu'))
 
-# Helper for hook tests: returns the "hook failed" line, with precise
-# wording that changed with Subversion 1.5.
-def hook_failure_message(hookname):
-  if svntest.main.server_minor_version < 5:
-    return "'%s' hook failed with error output:\n" % hookname
-  else:
-    if hookname in ["start-commit", "pre-commit"]:
-      action = "Commit"
-    elif hookname == "pre-revprop-change":
-      action = "Revprop change"
-    elif hookname == "pre-lock":
-      action = "Lock"
-    elif hookname == "pre-unlock":
-      action = "Unlock"
-    else:
-      action = None
-    if action is None:
-      message = "%s hook failed (exit code 1)" % (hookname,)
-    else:
-      message = "%s blocked by %s hook (exit code 1)" % (action, hookname)
-    return message + " with output:\n"
-
 
 #----------------------------------------------------------------------
 # Test if the post-commit error message is returned back to the svn
@@ -2098,8 +2076,10 @@
   wc_dir = sbox.wc_dir
   repo_dir = sbox.repo_dir
 
-  # Disable commits
-  svntest.actions.create_failing_post_commit_hook(repo_dir)
+  # Create a hook that outputs a message to stderr and returns exit code 1
+  # Include a non-XML-safe message to regression-test issue #3553.
+  error_msg = "Text with <angle brackets> & ampersand"
+  svntest.actions.create_failing_hook(repo_dir, "post-commit", error_msg)
 
   # Modify iota just so there is something to commit.
   iota_path = os.path.join(wc_dir, "iota")
@@ -2112,8 +2092,9 @@
                       "Transmitting file data .\n",
                       "Committed revision 2.\n",
                       "\n",
-                      "Warning: " + hook_failure_message('post-commit'),
-                      "Post-commit hook failed\n",
+                      "Warning: " +
+                        svntest.actions.hook_failure_message('post-commit'),
+                      error_msg + "\n",
                     ]
 
   svntest.actions.run_and_verify_svn(None, expected_output, [],
@@ -2464,13 +2445,9 @@
   repo_dir = sbox.repo_dir
 
   # Create a hook that outputs a message to stderr and returns exit code 1
-  hook_code = """import sys
-sys.stderr.write("Start-commit hook failed")
-sys.exit(1)"""
-
-  # Setup the hook configs to log data to a file
-  start_commit_hook = svntest.main.get_start_commit_hook_path(repo_dir)
-  svntest.main.create_python_hook_script(start_commit_hook, hook_code)
+  # Include a non-XML-safe message to regression-test issue #3553.
+  error_msg = "Text with <angle brackets> & ampersand"
+  svntest.actions.create_failing_hook(repo_dir, "start-commit", error_msg)
 
   # Modify iota just so there is something to commit.
   iota_path = os.path.join(wc_dir, "iota")
@@ -2488,8 +2465,9 @@
   # contain source code file and line numbers.
   if len(actual_stderr) > 2:
     actual_stderr = actual_stderr[-2:]
-  expected_stderr = [ "svn: " + hook_failure_message('start-commit'),
-                      "Start-commit hook failed\n"
+  expected_stderr = [ "svn: " +
+                        svntest.actions.hook_failure_message('start-commit'),
+                      error_msg + "\n",
                     ]
   svntest.verify.compare_and_display_lines('Start-commit hook test',
                                            'STDERR',
@@ -2507,13 +2485,9 @@
   repo_dir = sbox.repo_dir
 
   # Create a hook that outputs a message to stderr and returns exit code 1
-  hook_code = """import sys
-sys.stderr.write("Pre-commit hook failed")
-sys.exit(1)"""
-
-  # Setup the hook configs to log data to a file
-  pre_commit_hook = svntest.main.get_pre_commit_hook_path(repo_dir)
-  svntest.main.create_python_hook_script(pre_commit_hook, hook_code)
+  # Include a non-XML-safe message to regression-test issue #3553.
+  error_msg = "Text with <angle brackets> & ampersand"
+  svntest.actions.create_failing_hook(repo_dir, "pre-commit", error_msg)
 
   # Modify iota just so there is something to commit.
   iota_path = os.path.join(wc_dir, "iota")
@@ -2531,8 +2505,9 @@
   # contain source code file and line numbers.
   if len(actual_stderr) > 2:
     actual_stderr = actual_stderr[-2:]
-  expected_stderr = [ "svn: " + hook_failure_message('pre-commit'),
-                      "Pre-commit hook failed\n"
+  expected_stderr = [ "svn: " +
+                        svntest.actions.hook_failure_message('pre-commit'),
+                      error_msg + "\n",
                     ]
   svntest.verify.compare_and_display_lines('Pre-commit hook test',
                                            'STDERR',

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/export_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/export_tests.py?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/export_tests.py (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/export_tests.py Tue Jan  5 17:31:58 2010
@@ -422,6 +422,67 @@
                                         '.', expected_output,
                                         expected_disk)
 
+def export_ignoring_keyword_translation(sbox):
+  "export ignoring keyword translation"
+  sbox.build()
+
+  wc_dir = sbox.wc_dir
+
+  # Add a keyword to A/mu and set the svn:keywords property
+  # appropriately to make sure it's not translated during
+  # the export operation
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+  svntest.main.file_append(mu_path, '$LastChangedRevision$')
+  svntest.main.run_svn(None, 'ps', 'svn:keywords',
+                       'LastChangedRevision', mu_path)
+  svntest.main.run_svn(None, 'ci',
+                       '-m', 'Added keyword to mu', mu_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu',
+                      contents=expected_disk.desc['A/mu'].contents +
+                      '$LastChangedRevision$')
+
+  export_target = sbox.add_wc_path('export')
+
+  expected_output = svntest.main.greek_state.copy()
+  expected_output.wc_dir = export_target
+  expected_output.desc[''] = Item()
+  expected_output.tweak(contents=None, status='A ')
+
+  svntest.actions.run_and_verify_export(sbox.repo_url,
+                                        export_target,
+                                        expected_output,
+                                        expected_disk,
+                                        "--ignore-keywords")
+
+def export_working_copy_ignoring_keyword_translation(sbox):
+  "export working copy ignoring keyword translation"
+  sbox.build(read_only = True)
+
+  wc_dir = sbox.wc_dir
+
+  # Add a keyword to A/mu and set the svn:keywords property
+  # appropriately to make sure it's not translated during
+  # the export operation
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+  svntest.main.file_append(mu_path, '$LastChangedRevision$')
+  svntest.main.run_svn(None, 'ps', 'svn:keywords',
+                       'LastChangedRevision', mu_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu',
+                      contents=expected_disk.desc['A/mu'].contents +
+                      '$LastChangedRevision$')
+
+  export_target = sbox.add_wc_path('export')
+
+  svntest.actions.run_and_verify_export(wc_dir,
+                                        export_target,
+                                        svntest.wc.State(sbox.wc_dir, {}),
+                                        expected_disk,
+                                        "--ignore-keywords")
+
 ########################################################################
 # Run the tests
 
@@ -446,6 +507,8 @@
               export_creates_intermediate_folders,
               export_HEADplus1_fails,
               export_to_explicit_cwd,
+              export_ignoring_keyword_translation,
+              export_working_copy_ignoring_keyword_translation,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/externals_tests.py?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/externals_tests.py Tue Jan  5 17:31:58 2010
@@ -1456,6 +1456,108 @@
   ### TODO: Commit the propset and update a pristine working copy from
   ### r2 to r3.
 
+#----------------------------------------------------------------------
+
+# Issue #3552
+def wc_repos_file_externals(sbox):
+  "tag directory with file externals from wc to url"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_url = sbox.repo_url
+
+  # Add a file A/theta.
+  theta_path = os.path.join(wc_dir, 'A', 'theta')
+  svntest.main.file_write(theta_path, 'theta', 'w')
+  svntest.main.run_svn(None, 'add', theta_path)
+
+  # Created expected output tree for 'svn ci'
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/theta' : Item(verb='Adding'),
+    })
+
+  # Create expected status tree
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/theta' : Item(status='  ', wc_rev=2),
+    })
+
+  # Commit the new file, creating revision 2.
+  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                        expected_status, None, wc_dir)
+
+
+  # Create a file external on the file A/theta
+  C = os.path.join(wc_dir, 'A', 'C')
+  external = os.path.join(C, 'theta')
+  externals_prop = "^/A/theta theta\n"
+
+  # Set and commit the property.
+  change_external(C, externals_prop)
+
+
+  # Now, /A/C/theta is designated as a file external pointing to
+  # the file /A/theta, but the external file is not there yet.
+  # Try to actually insert the external file via a verified update:
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/C/theta'      : Item(status='E '),
+    })
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/theta'      : Item('theta'),
+    'A/C'          : Item(props={'svn:externals':externals_prop}),
+    'A/C/theta'    : Item('theta'),
+    })
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+  expected_status.add({
+    'A/theta'   : Item(status='  ', wc_rev=3),
+    'A/C/theta' : Item(status='  ', wc_rev=3, switched='X'),
+    })
+
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None, None, None,
+                                        True)
+
+  # Copy A/C to a new tag in the repos
+  tag_url = repo_url + '/A/I'
+  svntest.main.run_svn(None, 'cp', C, tag_url, '-m', 'create tag')
+
+  # Try to actually insert the external file (A/I/theta) via a verified update:
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/I'            : Item(status='A '),
+      'A/I/theta'      : Item(status='E '),
+    })
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'A/theta'      : Item('theta'),
+    'A/C'          : Item(props={'svn:externals':externals_prop}),
+    'A/C/theta'    : Item('theta'),
+    'A/I'          : Item(props={'svn:externals':externals_prop}),
+    'A/I/theta'    : Item('theta'),
+    })
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 4)
+  expected_status.add({
+    'A/theta'   : Item(status='  ', wc_rev=4),
+    'A/C/theta' : Item(status='  ', wc_rev=4, switched='X'),
+    'A/I'       : Item(status='  ', wc_rev=4),
+    'A/I/theta' : Item(status='  ', wc_rev=4, switched='X'),
+    })
+
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None, None, None,
+                                        True)
+
+
 ########################################################################
 # Run the tests
 
@@ -1484,6 +1586,7 @@
               XFail(switch_relative_external),
               export_sparse_wc_with_externals,
               relegate_external,
+              wc_repos_file_externals,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests.py?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests.py (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests.py Tue Jan  5 17:31:58 2010
@@ -78,8 +78,9 @@
                  (re.compile(r'version \d+\.\d+\.\d+ \(.*\)'),
                   'version X.Y.Z '),
                  # The copyright end date keeps changing; fix forever.
-                 (re.compile(r'Copyright \(C\) 2000-\d+ CollabNet\.'),
-                  'Copyright (C) YYYY-YYYY CollabNet'),
+                 (re.compile(r'Copyright \(C\) 20\d\d The Apache '
+                              'Software Foundation\.'),
+                  'Copyright (C) YYYY The Apache Software Foundation'),
                  # In 'svn --version --quiet', we print only the version
                  # number in a single line.
                  (re.compile(r'^\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?$'), 'X.Y.Z\n'),

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout Tue Jan  5 17:31:58 2010
@@ -1,7 +1,7 @@
 svn, version 0.16.0 (r3987)
    compiled Dec  5 2002, 00:02:51
 
-Copyright (C) 2009 The Apache Software Foundation.
+Copyright (C) 2010 The Apache Software Foundation.
 This software consists of contributions made by many people;
 see the NOTICE file for more information.
 Subversion is open source software, see http://subversion.apache.org/

Modified: subversion/branches/issue-3242-dev/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/issue-3242-dev/subversion/tests/cmdline/merge_tests.py?rev=896142&r1=896141&r2=896142&view=diff
==============================================================================
--- subversion/branches/issue-3242-dev/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/issue-3242-dev/subversion/tests/cmdline/merge_tests.py Tue Jan  5 17:31:58 2010
@@ -17164,6 +17164,130 @@
                                        expected_skip,
                                        None, None, None, None,
                                        None, 1, 0)  
+
+# Test for a reintegrate bug which can occur when the merge source
+# has mergeinfo that explicitly describes common history with the reintegrate
+# target, see http://mail-archives.apache.org/mod_mbox/subversion-dev/
+# 200912.mbox/%3C6cfe18eb0912161438wfb5234bj118aacdff7ffb25f@mail.gmail.com%3E
+def reintegrate_with_self_referential_mergeinfo(sbox):
+  "source has target's history as explicit mergeinfo"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Make some changes under 'A' in r2-5.
+  wc_disk, wc_status = set_up_branch(sbox, nbr_of_branches=0)
+
+  # Some paths we'll care about
+  A_path       = os.path.join(wc_dir, "A")
+  A2_path      = os.path.join(wc_dir, "A2")
+  A2_B_path    = os.path.join(wc_dir, "A2", "B")
+  A2_1_path    = os.path.join(wc_dir, "A2.1")
+  A2_1_mu_path = os.path.join(wc_dir, "A2.1", "mu")
+  
+  # r6 Copy A to A2 and then manually set some self-referential mergeinfo on
+  # A2/B and A2.
+  svntest.actions.run_and_verify_svn(None, ["At revision 5.\n"], [],
+                                     'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'copy', A_path, A2_path)
+  # /A:3 describes A2's natural history, a.k.a. it's implicit mergeinfo, so
+  # it is self-referential.  Same for /A/B:4 and A2/B.  Normally this is
+  # redundant but not harmful.
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'svn:mergeinfo', '/A:3', A2_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'svn:mergeinfo', '/A/B:4', A2_B_path)
+  svntest.actions.run_and_verify_svn(
+    None, None, [], 'ci', '-m',
+    'copy A to A2 and set some self-referential mergeinfo on the latter.',
+    wc_dir)
+
+  # r7 Copy A2 to A2.1
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'copy', A2_path, A2_1_path)
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'copy A2to A2.1.', wc_dir)
+
+  # r8 Make a change on A2.1/mu
+  svntest.main.file_write(A2_1_mu_path, 'New A2.1 stuff')
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+                                     '-m', 'Work done on the A2.1 branch.',
+                                     wc_dir)
+  
+  # Update to uniform revision and reintegrated A2.1 back to A2.
+  svntest.actions.run_and_verify_svn(None, ["At revision 8.\n"], [],
+                                     'up', wc_dir)
+
+  # Now merge all available revisions from A to A_COPY:
+  expected_output = wc.State(A2_path, {
+    'mu' : Item(status='U '),
+    })
+  expected_status = wc.State(A2_path, {
+    ''          : Item(status=' M'),
+    'B'         : Item(status=' M'),
+    'mu'        : Item(status='M '),
+    'B/E'       : Item(status='  '),
+    'B/E/alpha' : Item(status='  '),
+    'B/E/beta'  : Item(status='  '),
+    'B/lambda'  : Item(status='  '),
+    'B/F'       : Item(status='  '),
+    'C'         : Item(status='  '),
+    'D'         : Item(status='  '),
+    'D/G'       : Item(status='  '),
+    'D/G/pi'    : Item(status='  '),
+    'D/G/rho'   : Item(status='  '),
+    'D/G/tau'   : Item(status='  '),
+    'D/gamma'   : Item(status='  '),
+    'D/H'       : Item(status='  '),
+    'D/H/chi'   : Item(status='  '),
+    'D/H/psi'   : Item(status='  '),
+    'D/H/omega' : Item(status='  '),
+    })
+  expected_status.tweak(wc_rev=8)
+  expected_disk = wc.State('', {
+    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:3\n/A2.1:7-8'}),
+    'B'         : Item(props={SVN_PROP_MERGEINFO : '/A/B:4\n/A2.1/B:7-8'}),
+    'mu'        : Item("New A2.1 stuff"),
+    'B/E'       : Item(),
+    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+    'B/E/beta'  : Item("New content"),
+    'B/lambda'  : Item("This is the file 'lambda'.\n"),
+    'B/F'       : Item(),
+    'C'         : Item(),
+    'D'         : Item(),
+    'D/G'       : Item(),
+    'D/G/pi'    : Item("This is the file 'pi'.\n"),
+    'D/G/rho'   : Item("New content"),
+    'D/G/tau'   : Item("This is the file 'tau'.\n"),
+    'D/gamma'   : Item("This is the file 'gamma'.\n"),
+    'D/H'       : Item(),
+    'D/H/chi'   : Item("This is the file 'chi'.\n"),
+    'D/H/psi'   : Item("New content"),
+    'D/H/omega' : Item("New content"),
+    })
+  expected_skip = wc.State(A2_path, { })
+  # Previously failed with this error:
+  #
+  #   svn merge ^/A2.1" A2 --reintegrate
+  #  ..\..\..\subversion\svn\merge-cmd.c:349: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_client\merge.c:9219: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_client\ra.c:728: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_client\mergeinfo.c:733: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_client\ra.c:526: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_repos\rev_hunt.c:908: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_repos\rev_hunt.c:607: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_fs_fs\tree.c:2886: (apr_err=160013)
+  #  ..\..\..\subversion\libsvn_fs_fs\tree.c:669: (apr_err=160013)
+  #  svn: File not found: revision 4, path '/A2'
+  svntest.actions.run_and_verify_merge(A2_path, None, None,
+                                       sbox.repo_url + '/A2.1',
+                                       expected_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None,
+                                       None, 1, 0, '--reintegrate')
   
 ########################################################################
 # Run the tests
@@ -17394,6 +17518,7 @@
               XFail(committed_case_only_move_and_revert,
                     is_fs_case_insensitive),
               merge_into_wc_for_deleted_branch,
+              reintegrate_with_self_referential_mergeinfo,
              ]
 
 if __name__ == '__main__':



Mime
View raw message