You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2010/03/16 19:03:41 UTC

svn commit: r923910 [3/9] - in /subversion/branches/1.6.x-issue3432: ./ build/ build/ac-macros/ build/generator/ contrib/cgi/ contrib/client-side/emacs/ contrib/client-side/svn_load_dirs/ contrib/hook-scripts/ contrib/server-side/ doc/user/ notes/ pack...

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_client/repos_diff.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_client/repos_diff.c Tue Mar 16 18:03:37 2010
@@ -548,7 +548,6 @@ add_directory(const char *path,
   struct dir_baton *b;
   svn_wc_adm_access_t *adm_access;
   svn_wc_notify_state_t state;
-  svn_wc_notify_action_t action;
 
   /* ### TODO: support copyfrom? */
 
@@ -571,47 +570,56 @@ add_directory(const char *path,
           (adm_access, &state, &b->tree_conflicted, b->wcpath,
            eb->target_revision, eb->diff_cmd_baton));
 
-  if (b->tree_conflicted)
-    action = svn_wc_notify_tree_conflict;
-  else
-  if ((state == svn_wc_notify_state_missing)
-      || (state == svn_wc_notify_state_obstructed))
-    action = svn_wc_notify_skip;
-  else
-    action = svn_wc_notify_update_add;
-
+  /* Notifications for directories are done at close_directory time.
+   * But for paths at which the editor drive adds directories, we make an
+   * exception to this rule, so that the path appears in the output before
+   * any children of the newly added directory. Since a deletion at this path
+   * must have happened before this addition, we can safely notify about
+   * replaced directories here, too. */
   if (eb->notify_func)
     {
+      deleted_path_notify_t *dpn;
       svn_wc_notify_t *notify;
-      svn_boolean_t is_replace = FALSE;
-      deleted_path_notify_t *dpn = apr_hash_get(eb->deleted_paths, b->wcpath,
-                                              APR_HASH_KEY_STRING);
+      svn_wc_notify_action_t action;
+      svn_node_kind_t kind = svn_node_dir;
+      
+      /* Find out if a pending delete notification for this path is
+       * still around. */
+      dpn = apr_hash_get(eb->deleted_paths, b->wcpath, APR_HASH_KEY_STRING);
       if (dpn)
         {
-          svn_wc_notify_action_t new_action;
-          if (dpn->action == svn_wc_notify_update_delete
-              && action == svn_wc_notify_update_add)
-            {
-              is_replace = TRUE;
-              new_action = svn_wc_notify_update_replace;
-            }
-          else
-            new_action = dpn->action;
-          notify = svn_wc_create_notify(b->wcpath, new_action, pool);
-          notify->kind = dpn->kind;
-          notify->content_state = notify->prop_state = dpn->state;
-          notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-          (*eb->notify_func)(eb->notify_baton, notify, pool);
+          /* If any was found, we will handle the pending 'deleted path
+           * notification' (DPN) here. Remove it from the list. */
           apr_hash_set(eb->deleted_paths, b->wcpath,
                        APR_HASH_KEY_STRING, NULL);
+
+          /* the pending delete might be on a different node kind. */
+          kind = dpn->kind;
+          state = dpn->state;
         }
 
-      if (!is_replace)
+      /* Determine what the notification (ACTION) should be.
+       * In case of a pending 'delete', this might become a 'replace'. */
+      if (b->tree_conflicted)
+        action = svn_wc_notify_tree_conflict;
+      else if (dpn)
         {
-          notify = svn_wc_create_notify(b->wcpath, action, pool);
-          notify->kind = svn_node_dir;
-          (*eb->notify_func)(eb->notify_baton, notify, pool);
+          if (dpn->action == svn_wc_notify_update_delete)
+            action = svn_wc_notify_update_replace;
+          else
+            /* Note: dpn->action might be svn_wc_notify_tree_conflict */
+            action = dpn->action;
         }
+      else if (state == svn_wc_notify_state_missing ||
+               state == svn_wc_notify_state_obstructed)
+        action = svn_wc_notify_skip;
+      else
+        action = svn_wc_notify_update_add;
+
+      notify = svn_wc_create_notify(b->wcpath, action, pool);
+      notify->kind = kind;
+      notify->content_state = notify->prop_state = state;
+      (*eb->notify_func)(eb->notify_baton, notify, pool);
     }
 
   return SVN_NO_ERROR;
@@ -803,7 +811,6 @@ close_file(void *file_baton,
   struct edit_baton *eb = b->edit_baton;
   svn_wc_adm_access_t *adm_access;
   svn_error_t *err;
-  svn_wc_notify_action_t action;
   svn_wc_notify_state_t content_state = svn_wc_notify_state_unknown;
   svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
 
@@ -871,50 +878,54 @@ close_file(void *file_baton,
     }
 
 
-  if (b->tree_conflicted)
-    action = svn_wc_notify_tree_conflict;
-  else if ((content_state == svn_wc_notify_state_missing)
-            || (content_state == svn_wc_notify_state_obstructed))
-    action = svn_wc_notify_skip;
-  else if (b->added)
-    action = svn_wc_notify_update_add;
-  else
-    action = svn_wc_notify_update_update;
-
   if (eb->notify_func)
     {
+      deleted_path_notify_t *dpn;
       svn_wc_notify_t *notify;
-      svn_boolean_t is_replace = FALSE;
-      deleted_path_notify_t *dpn = apr_hash_get(eb->deleted_paths, b->wcpath,
-                                              APR_HASH_KEY_STRING);
+      svn_wc_notify_action_t action;
+      svn_node_kind_t kind = svn_node_file;
+      
+      /* Find out if a pending delete notification for this path is
+       * still around. */
+      dpn = apr_hash_get(eb->deleted_paths, b->wcpath, APR_HASH_KEY_STRING);
       if (dpn)
         {
-          svn_wc_notify_action_t new_action;
-          if (dpn->action == svn_wc_notify_update_delete
-              && action == svn_wc_notify_update_add)
-            {
-              is_replace = TRUE;
-              new_action = svn_wc_notify_update_replace;
-            }
-          else
-            new_action = dpn->action;
-          notify  = svn_wc_create_notify(b->wcpath, new_action, pool);
-          notify->kind = dpn->kind;
-          notify->content_state = notify->prop_state = dpn->state;
-          notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-          (*eb->notify_func)(eb->notify_baton, notify, pool);
+          /* If any was found, we will handle the pending 'deleted path
+           * notification' (DPN) here. Remove it from the list. */
           apr_hash_set(eb->deleted_paths, b->wcpath,
                        APR_HASH_KEY_STRING, NULL);
+
+          /* the pending delete might be on a different node kind. */
+          kind = dpn->kind;
+          content_state = prop_state = dpn->state;
         }
 
-      if (!is_replace)
+      /* Determine what the notification (ACTION) should be.
+       * In case of a pending 'delete', this might become a 'replace'. */
+      if (b->tree_conflicted)
+        action = svn_wc_notify_tree_conflict;
+      else if (dpn)
         {
-          notify = svn_wc_create_notify(b->wcpath, action, pool);
-          notify->kind = svn_node_file;
-          notify->content_state = content_state;
-          notify->prop_state = prop_state;
-          (*eb->notify_func)(eb->notify_baton, notify, pool);
+          if (dpn->action == svn_wc_notify_update_delete
+              && b->added)
+            action = svn_wc_notify_update_replace;
+          else
+            /* Note: dpn->action might be svn_wc_notify_tree_conflict */
+            action = dpn->action;
         }
+      else if ((content_state == svn_wc_notify_state_missing)
+                || (content_state == svn_wc_notify_state_obstructed))
+        action = svn_wc_notify_skip;
+      else if (b->added)
+        action = svn_wc_notify_update_add;
+      else
+        action = svn_wc_notify_update_update;
+
+      notify = svn_wc_create_notify(b->wcpath, action, pool);
+      notify->kind = kind;
+      notify->content_state = content_state;
+      notify->prop_state = prop_state;
+      (*eb->notify_func)(eb->notify_baton, notify, pool);
     }
 
   return SVN_NO_ERROR;
@@ -945,8 +956,10 @@ close_directory(void *dir_baton,
   if (err && err->apr_err == SVN_ERR_WC_NOT_LOCKED)
     {
       /* ### maybe try to stat the local b->wcpath? */
-      /* If the path doesn't exist, then send a 'skipped' notification. */
-      if (eb->notify_func)
+      /* If the path doesn't exist, then send a 'skipped' notification. 
+         Don't notify added directories as they triggered notification
+         in add_directory. */
+      if (! b->added && eb->notify_func)
         {
           svn_wc_notify_t *notify
             = svn_wc_create_notify(b->wcpath,
@@ -984,9 +997,8 @@ close_directory(void *dir_baton,
           (adm_access, NULL, NULL, NULL,
            b->wcpath, b->edit_baton->diff_cmd_baton));
 
-  /* ### Don't notify added directories as they triggered notification
-     in add_directory.  Does this mean that directory notification
-     isn't getting all the information? */
+  /* Don't notify added directories as they triggered notification
+     in add_directory. */
   if (!b->added && eb->notify_func)
     {
       svn_wc_notify_t *notify;

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_client/revisions.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_client/revisions.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_client/revisions.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_client/revisions.c Tue Mar 16 18:03:37 2010
@@ -129,9 +129,12 @@ svn_client__get_revision_number(svn_revn
     }
 
   /* Final check -- if our caller provided a youngest revision, and
-  the number we wound up with is younger than that revision, we need
-  to stick to our caller's idea of "youngest". */
+     the number we wound up with (after talking to the server) is younger
+     than that revision, we need to stick to our caller's idea of "youngest".
+   */
   if (youngest_rev
+      && (revision->kind == svn_opt_revision_head
+          || revision->kind == svn_opt_revision_date)
       && SVN_IS_VALID_REVNUM(*youngest_rev)
       && SVN_IS_VALID_REVNUM(*revnum)
       && (*revnum > *youngest_rev))

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/svndiff.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/svndiff.c Tue Mar 16 18:03:37 2010
@@ -55,10 +55,23 @@ struct encoder_baton {
   apr_pool_t *pool;
 };
 
+/* This is at least as big as the largest size of an integer that
+   encode_int can generate; it is sufficient for creating buffers for
+   it to write into.  This assumes that integers are at most 64 bits,
+   and so 10 bytes (with 7 bits of information each) are sufficient to
+   represent them. */
+#define MAX_ENCODED_INT_LEN 10
+/* This is at least as big as the largest size for a single instruction. */
+#define MAX_INSTRUCTION_LEN (2*MAX_ENCODED_INT_LEN+1)
+/* This is at least as big as the largest possible instructions
+   section: in theory, the instructions could be SVN_DELTA_WINDOW_SIZE
+   1-byte copy-from-source instructions (though this is very unlikely). */
+#define MAX_INSTRUCTION_SECTION_LEN (SVN_DELTA_WINDOW_SIZE*MAX_INSTRUCTION_LEN)
 
 /* Encode VAL into the buffer P using the variable-length svndiff
    integer format.  Return the incremented value of P after the
-   encoded bytes have been written.
+   encoded bytes have been written.  P must point to a buffer of size
+   at least MAX_ENCODED_INT_LEN.
 
    This encoding uses the high bit of each byte as a continuation bit
    and the other seven bits as data bits.  High-order data bits are
@@ -80,7 +93,7 @@ encode_int(char *p, svn_filesize_t val)
   svn_filesize_t v;
   unsigned char cont;
 
-  assert(val >= 0);
+  SVN_ERR_ASSERT_NO_RETURN(val >= 0);
 
   /* Figure out how many bytes we'll need.  */
   v = val >> 7;
@@ -91,6 +104,8 @@ encode_int(char *p, svn_filesize_t val)
       n++;
     }
 
+  SVN_ERR_ASSERT_NO_RETURN(n <= MAX_ENCODED_INT_LEN);
+
   /* Encode the remaining bytes; n is always the number of bytes
      coming after the one we're encoding.  */
   while (--n >= 0)
@@ -107,7 +122,7 @@ encode_int(char *p, svn_filesize_t val)
 static void
 append_encoded_int(svn_stringbuf_t *header, svn_filesize_t val)
 {
-  char buf[128], *p;
+  char buf[MAX_ENCODED_INT_LEN], *p;
 
   p = encode_int(buf, val);
   svn_stringbuf_appendbytes(header, buf, p - buf);
@@ -163,7 +178,7 @@ window_handler(svn_txdelta_window_t *win
   svn_stringbuf_t *i1 = svn_stringbuf_create("", pool);
   svn_stringbuf_t *header = svn_stringbuf_create("", pool);
   const svn_string_t *newdata;
-  char ibuf[128], *ip;
+  char ibuf[MAX_INSTRUCTION_LEN], *ip;
   const svn_txdelta_op_t *op;
   apr_size_t len;
 
@@ -341,6 +356,8 @@ decode_file_offset(svn_filesize_t *val,
                    const unsigned char *p,
                    const unsigned char *end)
 {
+  if (p + MAX_ENCODED_INT_LEN < end)
+    end = p + MAX_ENCODED_INT_LEN;
   /* Decode bytes until we're done.  */
   *val = 0;
   while (p < end)
@@ -360,6 +377,8 @@ decode_size(apr_size_t *val,
             const unsigned char *p,
             const unsigned char *end)
 {
+  if (p + MAX_ENCODED_INT_LEN < end)
+    end = p + MAX_ENCODED_INT_LEN;
   /* Decode bytes until we're done.  */
   *val = 0;
   while (p < end)
@@ -377,7 +396,7 @@ decode_size(apr_size_t *val,
    data is not compressed.  */
 
 static svn_error_t *
-zlib_decode(svn_stringbuf_t *in, svn_stringbuf_t *out)
+zlib_decode(svn_stringbuf_t *in, svn_stringbuf_t *out, apr_size_t limit)
 {
   apr_size_t len;
   char *oldplace = in->data;
@@ -385,6 +404,13 @@ zlib_decode(svn_stringbuf_t *in, svn_str
   /* First thing in the string is the original length.  */
   in->data = (char *)decode_size(&len, (unsigned char *)in->data,
                                  (unsigned char *)in->data+in->len);
+  if (in->data == NULL)
+    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
+                            _("Decompression of svndiff data failed: no size"));
+  if (len > limit)
+    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
+                            _("Decompression of svndiff data failed: "
+                              "size too large"));
   /* We need to subtract the size of the encoded original length off the
    *      still remaining input length.  */
   in->len -= (in->data - oldplace);
@@ -482,10 +508,10 @@ count_and_verify_instructions(int *ninst
         return svn_error_createf
           (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
            _("Invalid diff stream: insn %d cannot be decoded"), n);
-      else if (op.length <= 0)
+      else if (op.length == 0)
         return svn_error_createf
           (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
-           _("Invalid diff stream: insn %d has non-positive length"), n);
+           _("Invalid diff stream: insn %d has length zero"), n);
       else if (op.length > tview_len - tpos)
         return svn_error_createf
           (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
@@ -494,7 +520,8 @@ count_and_verify_instructions(int *ninst
       switch (op.action_code)
         {
         case svn_txdelta_source:
-          if (op.length > sview_len - op.offset)
+          if (op.length > sview_len - op.offset ||
+              op.offset > sview_len)
             return svn_error_createf
               (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,
                _("Invalid diff stream: "
@@ -560,11 +587,11 @@ decode_window(svn_txdelta_window_t *wind
 
       instin = svn_stringbuf_ncreate((const char *)data, insend - data, pool);
       instout = svn_stringbuf_create("", pool);
-      SVN_ERR(zlib_decode(instin, instout));
+      SVN_ERR(zlib_decode(instin, instout, MAX_INSTRUCTION_SECTION_LEN));
 
       ndin = svn_stringbuf_ncreate((const char *)insend, newlen, pool);
       ndout = svn_stringbuf_create("", pool);
-      SVN_ERR(zlib_decode(ndin, ndout));
+      SVN_ERR(zlib_decode(ndin, ndout, SVN_DELTA_WINDOW_SIZE));
 
       newlen = ndout->len;
       data = (unsigned char *)instout->data;
@@ -680,6 +707,14 @@ write_handler(void *baton,
       if (p == NULL)
         return SVN_NO_ERROR;
 
+      if (tview_len > SVN_DELTA_WINDOW_SIZE ||
+          sview_len > SVN_DELTA_WINDOW_SIZE ||
+          /* for svndiff1, newlen includes the original length */
+          newlen > SVN_DELTA_WINDOW_SIZE + MAX_ENCODED_INT_LEN ||
+          inslen > MAX_INSTRUCTION_SECTION_LEN)
+        return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,
+                                _("Svndiff contains a too-large window"));
+
       /* Check for integer overflow.  */
       if (sview_offset < 0 || inslen + newlen < inslen
           || sview_len + tview_len < sview_len
@@ -836,6 +871,14 @@ read_window_header(svn_stream_t *stream,
   SVN_ERR(read_one_size(inslen, stream));
   SVN_ERR(read_one_size(newlen, stream));
 
+  if (*tview_len > SVN_DELTA_WINDOW_SIZE ||
+      *sview_len > SVN_DELTA_WINDOW_SIZE ||
+      /* for svndiff1, newlen includes the original length */
+      *newlen > SVN_DELTA_WINDOW_SIZE + MAX_ENCODED_INT_LEN ||
+      *inslen > MAX_INSTRUCTION_SECTION_LEN)
+    return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,
+                            _("Svndiff contains a too-large window"));
+
   /* Check for integer overflow.  */
   if (*sview_offset < 0 || *inslen + *newlen < *inslen
       || *sview_len + *tview_len < *sview_len

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/text_delta.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_delta/text_delta.c Tue Mar 16 18:03:37 2010
@@ -543,7 +543,7 @@ svn_txdelta_target_push(svn_txdelta_wind
 /* Functions for applying deltas.  */
 
 /* Ensure that BUF has enough space for VIEW_LEN bytes.  */
-static APR_INLINE void
+static APR_INLINE svn_error_t *
 size_buffer(char **buf, apr_size_t *buf_size,
             apr_size_t view_len, apr_pool_t *pool)
 {
@@ -552,8 +552,11 @@ size_buffer(char **buf, apr_size_t *buf_
       *buf_size *= 2;
       if (*buf_size < view_len)
         *buf_size = view_len;
+      SVN_ERR_ASSERT(APR_ALIGN_DEFAULT(*buf_size) >= *buf_size);
       *buf = apr_palloc(pool, *buf_size);
     }
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -654,7 +657,7 @@ apply_window(svn_txdelta_window_t *windo
                          >= ab->sbuf_offset + ab->sbuf_len)));
 
   /* Make sure there's enough room in the target buffer.  */
-  size_buffer(&ab->tbuf, &ab->tbuf_size, window->tview_len, ab->pool);
+  SVN_ERR(size_buffer(&ab->tbuf, &ab->tbuf_size, window->tview_len, ab->pool));
 
   /* Prepare the source buffer for reading from the input stream.  */
   if (window->sview_offset != ab->sbuf_offset
@@ -663,7 +666,8 @@ apply_window(svn_txdelta_window_t *windo
       char *old_sbuf = ab->sbuf;
 
       /* Make sure there's enough room.  */
-      size_buffer(&ab->sbuf, &ab->sbuf_size, window->sview_len, ab->pool);
+      SVN_ERR(size_buffer(&ab->sbuf, &ab->sbuf_size, window->sview_len,
+              ab->pool));
 
       /* If the existing view overlaps with the new view, copy the
        * overlap to the beginning of the new buffer.  */

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_fs_fs/fs_fs.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_fs_fs/fs_fs.c Tue Mar 16 18:03:37 2010
@@ -790,7 +790,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
   if (!err)
     {
       apr_off_t offset = 0;
-      err = svn_io_file_seek(*file, APR_END, &offset, 0);
+      err = svn_io_file_seek(*file, APR_END, &offset, pool);
     }
 
   if (err)
@@ -1419,6 +1419,9 @@ svn_fs_fs__hotcopy(const char *src_path,
   /* Copy the uuid. */
   SVN_ERR(svn_io_dir_file_copy(src_path, dst_path, PATH_UUID, pool));
 
+  /* Copy the config. */
+  SVN_ERR(svn_io_dir_file_copy(src_path, dst_path, PATH_CONFIG, pool));
+
   /* Copy the min unpacked rev, and read its value. */
   if (format >= SVN_FS_FS__MIN_PACKED_FORMAT)
     {
@@ -4375,7 +4378,8 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
                             apr_array_header_t *props,
                             apr_pool_t *pool)
 {
-  apr_file_t *txn_prop_file;
+  const char *txn_prop_filename;
+  svn_stringbuf_t *buf;
   svn_stream_t *stream;
   apr_hash_t *txn_prop = apr_hash_make(pool);
   int i;
@@ -4400,15 +4404,19 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
 
   /* Create a new version of the file and write out the new props. */
   /* Open the transaction properties file. */
-  SVN_ERR(svn_io_file_open(&txn_prop_file,
-                           path_txn_props(txn->fs, txn->id, pool),
-                           APR_WRITE | APR_CREATE | APR_TRUNCATE
-                           | APR_BUFFERED, APR_OS_DEFAULT, pool));
-
-  stream = svn_stream_from_aprfile2(txn_prop_file, FALSE, pool);
+  buf = svn_stringbuf_create_ensure(1024, pool);
+  stream = svn_stream_from_stringbuf(buf, pool);
   SVN_ERR(svn_hash_write2(txn_prop, stream, SVN_HASH_TERMINATOR, pool));
-
-  return svn_stream_close(stream);
+  SVN_ERR(svn_stream_close(stream));
+  SVN_ERR(svn_io_write_unique(&txn_prop_filename,
+                              path_txn_dir(txn->fs, txn->id, pool),
+                              buf->data,
+                              buf->len,
+                              svn_io_file_del_none,
+                              pool));
+  return svn_io_file_rename(txn_prop_filename,
+                            path_txn_props(txn->fs, txn->id, pool),
+                            pool);
 }
 
 svn_error_t *

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_neon/commit.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_neon/commit.c Tue Mar 16 18:03:37 2010
@@ -42,6 +42,7 @@
 #include "ra_neon.h"
 
 
+#define APPLY_TO_VERSION "<D:apply-to-version/>"
 /*
 ** version_rsrc_t: identify the relevant pieces of a resource on the server
 **
@@ -393,6 +394,7 @@ static svn_error_t * do_checkout(commit_
                                  const char *vsn_url,
                                  svn_boolean_t allow_404,
                                  const char *token,
+                                 svn_boolean_t is_vcc,
                                  int *code,
                                  const char **locn,
                                  apr_pool_t *pool)
@@ -417,7 +419,9 @@ static svn_error_t * do_checkout(commit_
                       "<D:checkout xmlns:D=\"DAV:\">"
                       "<D:activity-set>"
                       "<D:href>%s</D:href>"
-                      "</D:activity-set></D:checkout>", cc->activity_url);
+                      "</D:activity-set>%s</D:checkout>",
+                      cc->activity_url,
+                      is_vcc ? APPLY_TO_VERSION: "");
 
   if (token)
     {
@@ -453,6 +457,7 @@ static svn_error_t * checkout_resource(c
                                        version_rsrc_t *rsrc,
                                        svn_boolean_t allow_404,
                                        const char *token,
+                                       svn_boolean_t is_vcc,
                                        apr_pool_t *pool)
 {
   int code;
@@ -467,7 +472,8 @@ static svn_error_t * checkout_resource(c
     }
 
   /* check out the Version Resource */
-  err = do_checkout(cc, rsrc->vsn_url, allow_404, token, &code, &locn, pool);
+  err = do_checkout(cc, rsrc->vsn_url, allow_404, token,
+                    is_vcc, &code, &locn, pool);
 
   /* possibly run the request again, with a re-fetched Version Resource */
   if (err == NULL && allow_404 && code == 404)
@@ -478,7 +484,8 @@ static svn_error_t * checkout_resource(c
       SVN_ERR(get_version_url(cc, NULL, rsrc, TRUE, pool));
 
       /* do it again, but don't allow a 404 this time */
-      err = do_checkout(cc, rsrc->vsn_url, FALSE, token, &code, &locn, pool);
+      err = do_checkout(cc, rsrc->vsn_url, FALSE, token,
+                        is_vcc, &code, &locn, pool);
     }
 
   /* special-case when conflicts occur */
@@ -705,7 +712,8 @@ static svn_error_t * commit_delete_entry
     }
 
   /* get the URL to the working collection */
-  SVN_ERR(checkout_resource(parent->cc, parent->rsrc, TRUE, NULL, pool));
+  SVN_ERR(checkout_resource(parent->cc, parent->rsrc, TRUE,
+                            NULL, FALSE, pool));
 
   /* create the URL for the child resource */
   child = svn_path_url_add_component(parent->rsrc->wr_url, name, pool);
@@ -841,7 +849,8 @@ static svn_error_t * commit_add_dir(cons
 
   /* check out the parent resource so that we can create the new collection
      as one of its children. */
-  SVN_ERR(checkout_resource(parent->cc, parent->rsrc, TRUE, NULL, dir_pool));
+  SVN_ERR(checkout_resource(parent->cc, parent->rsrc, TRUE,
+                            NULL, FALSE, dir_pool));
 
   /* create a child object that contains all the resource urls */
   child = apr_pcalloc(dir_pool, sizeof(*child));
@@ -953,7 +962,7 @@ static svn_error_t * commit_change_dir_p
   record_prop_change(dir->pool, dir, name, value);
 
   /* do the CHECKOUT sooner rather than later */
-  SVN_ERR(checkout_resource(dir->cc, dir->rsrc, TRUE, NULL, pool));
+  SVN_ERR(checkout_resource(dir->cc, dir->rsrc, TRUE, NULL, FALSE, pool));
 
   /* Add this path to the valid targets hash. */
   add_valid_target(dir->cc, dir->rsrc->local_path, svn_nonrecursive);
@@ -994,7 +1003,8 @@ static svn_error_t * commit_add_file(con
   */
 
   /* Do the parent CHECKOUT first */
-  SVN_ERR(checkout_resource(parent->cc, parent->rsrc, TRUE, NULL, workpool));
+  SVN_ERR(checkout_resource(parent->cc, parent->rsrc, TRUE,
+                            NULL, FALSE, workpool));
 
   /* Construct a file_baton that contains all the resource urls. */
   file = apr_pcalloc(file_pool, sizeof(*file));
@@ -1133,7 +1143,7 @@ static svn_error_t * commit_open_file(co
 
   /* do the CHECKOUT now. we'll PUT the new file contents later on. */
   SVN_ERR(checkout_resource(parent->cc, file->rsrc, TRUE,
-                            file->token, workpool));
+                            file->token, FALSE, workpool));
 
   /* ### wait for apply_txdelta before doing a PUT. it might arrive a
      ### "long time" from now. certainly after many other operations, so
@@ -1240,7 +1250,8 @@ static svn_error_t * commit_change_file_
   record_prop_change(file->pool, file, name, value);
 
   /* do the CHECKOUT sooner rather than later */
-  SVN_ERR(checkout_resource(file->cc, file->rsrc, TRUE, file->token, pool));
+  SVN_ERR(checkout_resource(file->cc, file->rsrc, TRUE,
+                            file->token, FALSE, pool));
 
   /* Add this path to the valid targets hash. */
   add_valid_target(file->cc, file->rsrc->local_path, svn_nonrecursive);
@@ -1376,8 +1387,7 @@ static svn_error_t * apply_revprops(comm
                                     apr_pool_t *pool)
 {
   const char *vcc;
-  const svn_string_t *baseline_url;
-  version_rsrc_t baseline_rsrc = { SVN_INVALID_REVNUM };
+  version_rsrc_t vcc_rsrc = { SVN_INVALID_REVNUM };
   svn_error_t *err = NULL;
   int retry_count = 5;
 
@@ -1387,24 +1397,17 @@ static svn_error_t * apply_revprops(comm
   /* fetch the DAV:version-controlled-configuration from the session's URL */
   SVN_ERR(svn_ra_neon__get_vcc(&vcc, cc->ras, cc->ras->root.path, pool));
 
-  /* ### we should use DAV:apply-to-version on the CHECKOUT so we can skip
-     ### retrieval of the baseline */
 
   do {
 
     svn_error_clear(err);
 
-    /* Get the latest baseline from VCC's DAV:checked-in property.
-       This should give us the HEAD revision of the moment. */
-    SVN_ERR(svn_ra_neon__get_one_prop(&baseline_url, cc->ras,
-                                      vcc, NULL,
-                                      &svn_ra_neon__checked_in_prop, pool));
-    baseline_rsrc.pool = pool;
-    baseline_rsrc.vsn_url = baseline_url->data;
+    vcc_rsrc.pool = pool;
+    vcc_rsrc.vsn_url = vcc;
 
     /* To set the revision properties, we must checkout the latest baseline
        and get back a mutable "working" baseline.  */
-    err = checkout_resource(cc, &baseline_rsrc, FALSE, NULL, pool);
+    err = checkout_resource(cc, &vcc_rsrc, FALSE, NULL, TRUE, pool);
 
     /* There's a small chance of a race condition here, if apache is
        experiencing heavy commit concurrency or if the network has
@@ -1424,7 +1427,7 @@ static svn_error_t * apply_revprops(comm
   if (err)
     return err;
 
-  return svn_ra_neon__do_proppatch(cc->ras, baseline_rsrc.wr_url, revprop_table,
+  return svn_ra_neon__do_proppatch(cc->ras, vcc_rsrc.wr_url, revprop_table,
                                    NULL, NULL, pool);
 }
 

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/blame.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/blame.c Tue Mar 16 18:03:37 2010
@@ -432,8 +432,8 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
   svn_ra_serf__add_close_tag_buckets(buckets, session->bkt_alloc,
                                      "S:file-revs-report");
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         session, session->repos_url.path,
+  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
+                                         NULL, session->repos_url.path,
                                          end, NULL, pool));
   req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);
 

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/commit.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/commit.c Tue Mar 16 18:03:37 2010
@@ -82,8 +82,8 @@ typedef struct {
   /* The checked-in root to base CHECKOUTs from */
   const char *checked_in_url;
 
-  /* The root baseline collection */
-  const char *baseline_url;
+  /* vcc url */
+  const char *vcc_url;  
 
   /* Deleted files - so we can detect delete+add (replace) ops. */
   apr_hash_t *deleted_entries;
@@ -248,6 +248,7 @@ create_checkout_body(void *baton,
 
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:href");
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:activity-set");
+  svn_ra_serf__add_tag_buckets(body_bkt, "D:apply-to-version", NULL, alloc);
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:checkout");
 
   return body_bkt;
@@ -376,7 +377,7 @@ checkout_dir(dir_context_t *dir)
    */
   if (!dir->parent_dir && !dir->commit->baseline)
     {
-      checkout_ctx->checkout_url = dir->commit->baseline_url;
+      checkout_ctx->checkout_url = dir->commit->vcc_url;
       dir->commit->baseline = checkout_ctx;
     }
   else
@@ -469,13 +470,33 @@ get_version_url(const char **checked_in_
     {
       svn_ra_serf__propfind_context_t *propfind_ctx;
       apr_hash_t *props;
+      const char *propfind_url;
 
       props = apr_hash_make(pool);
 
       propfind_ctx = NULL;
-      svn_ra_serf__deliver_props(&propfind_ctx, props, session,
-                                 conn, session->repos_url.path,
-                                 base_revision, "0",
+      if (SVN_IS_VALID_REVNUM(base_revision))
+        {
+          const char *bc_url, *bc_relpath;
+          
+          /* mod_dav_svn can't handle the "Label:" header that
+             svn_ra_serf__deliver_props() is going to try to use for
+             this lookup, so we'll do things the hard(er) way, by
+             looking up the version URL from a resource in the
+             baseline collection. */
+          SVN_ERR(svn_ra_serf__get_baseline_info(&bc_url, &bc_relpath,
+                                                 session, conn,
+                                                 session->repos_url.path,
+                                                 base_revision, NULL, pool));
+          propfind_url = svn_path_url_add_component2(bc_url, bc_relpath, pool);
+        }
+      else
+        {
+          propfind_url = session->repos_url.path;
+        }
+
+      svn_ra_serf__deliver_props(&propfind_ctx, props, session, conn,
+                                 propfind_url, base_revision, "0",
                                  checked_in_props, FALSE, NULL, pool);
 
       SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, session, pool));
@@ -483,7 +504,7 @@ get_version_url(const char **checked_in_
       /* We wouldn't get here if the url wasn't found (404), so the checked-in
          property should have been set. */
       root_checkout =
-          svn_ra_serf__get_ver_prop(props, session->repos_url.path,
+          svn_ra_serf__get_ver_prop(props, propfind_url,
                                     base_revision, "DAV:", "checked-in");
 
       if (!root_checkout)
@@ -966,14 +987,11 @@ open_root(void *edit_baton,
 {
   commit_context_t *ctx = edit_baton;
   svn_ra_serf__options_context_t *opt_ctx;
-  svn_ra_serf__propfind_context_t *propfind_ctx;
   svn_ra_serf__handler_t *handler;
   svn_ra_serf__simple_request_context_t *mkact_ctx;
   proppatch_context_t *proppatch_ctx;
   dir_context_t *dir;
   const char *activity_str;
-  const char *vcc_url;
-  apr_hash_t *props;
   apr_hash_index_t *hi;
   svn_error_t *err;
 
@@ -1036,31 +1054,11 @@ open_root(void *edit_baton,
                                ctx->session->repos_url.hostinfo);
     }
 
-  SVN_ERR(svn_ra_serf__discover_root(&vcc_url, NULL,
+  SVN_ERR(svn_ra_serf__discover_root(&(ctx->vcc_url), NULL,
                                      ctx->session, ctx->conn,
                                      ctx->session->repos_url.path,
                                      ctx->pool));
 
-  /* Now go fetch our VCC and baseline so we can do a CHECKOUT. */
-  props = apr_hash_make(ctx->pool);
-  propfind_ctx = NULL;
-  svn_ra_serf__deliver_props(&propfind_ctx, props, ctx->session,
-                             ctx->conn, vcc_url, SVN_INVALID_REVNUM, "0",
-                             checked_in_props, FALSE, NULL, ctx->pool);
-
-  SVN_ERR(svn_ra_serf__wait_for_props(propfind_ctx, ctx->session, ctx->pool));
-
-  ctx->baseline_url = svn_ra_serf__get_ver_prop(props, vcc_url,
-                                                SVN_INVALID_REVNUM,
-                                                "DAV:", "checked-in");
-
-  if (!ctx->baseline_url)
-    {
-      return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
-                              _("The OPTIONS response did not include the "
-                                "requested checked-in value"));
-    }
-
   dir = apr_pcalloc(dir_pool, sizeof(*dir));
 
   dir->pool = dir_pool;

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/get_deleted_rev.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/get_deleted_rev.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/get_deleted_rev.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/get_deleted_rev.c Tue Mar 16 18:03:37 2010
@@ -197,7 +197,7 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
   drev_ctx->done = FALSE;
 
   SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         ras, NULL, peg_revision, NULL,
+                                         ras, NULL, NULL, peg_revision, NULL,
                                          pool));
 
   req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocations.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocations.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocations.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocations.c Tue Mar 16 18:03:37 2010
@@ -225,8 +225,8 @@ svn_ra_serf__get_locations(svn_ra_sessio
   svn_ra_serf__add_close_tag_buckets(buckets, session->bkt_alloc,
                                      "S:get-locations");
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         session, NULL, peg_revision, NULL,
+  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
+                                         NULL, NULL, peg_revision, NULL,
                                          pool));
 
   req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocationsegments.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/getlocationsegments.c Tue Mar 16 18:03:37 2010
@@ -173,9 +173,8 @@ svn_ra_serf__get_location_segments(svn_r
   svn_ra_serf__add_close_tag_buckets(buckets, session->bkt_alloc,
                                      "S:get-location-segments");
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         session, NULL, peg_revision, NULL,
-                                         pool));
+  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
+                                         NULL, NULL, peg_revision, NULL, pool));
 
   req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);
 

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/log.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/log.c Tue Mar 16 18:03:37 2010
@@ -573,9 +573,8 @@ svn_ra_serf__get_log(svn_ra_session_t *r
    */
   peg_rev = (start > end) ? start : end;
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         session, NULL, peg_rev, NULL,
-                                         pool));
+  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
+                                         NULL, NULL, peg_rev, NULL, pool));
 
   req_url = svn_path_url_add_component(basecoll_url, relative_url, pool);
 

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/mergeinfo.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/mergeinfo.c Tue Mar 16 18:03:37 2010
@@ -237,9 +237,8 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio
   const char *relative_url, *basecoll_url;
   const char *path;
 
-  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                         session, NULL, revision,
-                                         NULL, pool));
+  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
+                                         NULL, NULL, revision, NULL, pool));
 
   path = svn_path_url_add_component(basecoll_url, relative_url, pool);
 

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/property.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/property.c Tue Mar 16 18:03:37 2010
@@ -928,6 +928,7 @@ svn_error_t *
 svn_ra_serf__get_baseline_info(const char **bc_url,
                                const char **bc_relative,
                                svn_ra_serf__session_t *session,
+                               svn_ra_serf__connection_t *conn,
                                const char *url,
                                svn_revnum_t revision,
                                svn_revnum_t *latest_revnum,
@@ -940,12 +941,17 @@ svn_ra_serf__get_baseline_info(const cha
   if (! url)
     url = session->repos_url.path;
 
+  /* If the caller didn't provide a specific connection for us to use,
+     we'll use the default one.  */
+  if (! conn)
+    conn = session->conns[0];
+
   SVN_ERR(svn_ra_serf__discover_root(&vcc_url, &relative_url,
-                                     session, session->conns[0], url, pool));
+                                     session, conn, url, pool));
 
   if (revision != SVN_INVALID_REVNUM)
     {
-      SVN_ERR(svn_ra_serf__retrieve_props(props, session, session->conns[0],
+      SVN_ERR(svn_ra_serf__retrieve_props(props, session, conn,
                                           vcc_url, revision, "0",
                                           baseline_props, pool));
       basecoll_url = svn_ra_serf__get_ver_prop(props, vcc_url, revision,
@@ -953,7 +959,7 @@ svn_ra_serf__get_baseline_info(const cha
     }
   else
     {
-      SVN_ERR(svn_ra_serf__retrieve_props(props, session, session->conns[0],
+      SVN_ERR(svn_ra_serf__retrieve_props(props, session, conn,
                                           vcc_url, revision, "0",
                                           checked_in_props, pool));
       baseline_url = svn_ra_serf__get_ver_prop(props, vcc_url, revision,
@@ -965,7 +971,7 @@ svn_ra_serf__get_baseline_info(const cha
                                     "requested checked-in value"));
         }
 
-      SVN_ERR(svn_ra_serf__retrieve_props(props, session, session->conns[0],
+      SVN_ERR(svn_ra_serf__retrieve_props(props, session, conn,
                                           baseline_url, revision, "0",
                                           baseline_props, pool));
       basecoll_url = svn_ra_serf__get_ver_prop(props, baseline_url, revision,
@@ -979,6 +985,8 @@ svn_ra_serf__get_baseline_info(const cha
                                 "requested baseline-collection value"));
     }
 
+  basecoll_url = svn_path_canonicalize(basecoll_url, pool);
+
   if (latest_revnum)
     {
       const char *version_name;

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/ra_serf.h?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/ra_serf.h Tue Mar 16 18:03:37 2010
@@ -1041,12 +1041,16 @@ svn_ra_serf__discover_root(const char **
  * REVISION was set to SVN_INVALID_REVNUM, this will return the current
  * HEAD revision.
  *
+ * If non-NULL, use CONN for communications with the server;
+ * otherwise, use the default connection.
+ *
  * Use POOL for all allocations.
  */
 svn_error_t *
 svn_ra_serf__get_baseline_info(const char **bc_url,
                                const char **bc_relative,
                                svn_ra_serf__session_t *session,
+                               svn_ra_serf__connection_t *conn,
                                const char *url,
                                svn_revnum_t revision,
                                svn_revnum_t *latest_revnum,

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/serf.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_serf/serf.c Tue Mar 16 18:03:37 2010
@@ -628,8 +628,8 @@ svn_ra_serf__get_latest_revnum(svn_ra_se
   const char *relative_url, *basecoll_url;
   svn_ra_serf__session_t *session = ra_session->priv;
 
-  return svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                        session, session->repos_url.path,
+  return svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
+                                        NULL, session->repos_url.path,
                                         SVN_INVALID_REVNUM, latest_revnum,
                                         pool);
 }
@@ -717,7 +717,7 @@ fetch_path_props(svn_ra_serf__propfind_c
       const char *relative_url, *basecoll_url;
 
       SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                             session, path,
+                                             session, NULL, path,
                                              revision, NULL, pool));
 
       /* We will try again with our new path; however, we're now
@@ -988,7 +988,7 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
       const char *relative_url, *basecoll_url;
 
       SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
-                                             session, path, revision,
+                                             session, NULL, path, revision,
                                              fetched_rev, pool));
 
       path = svn_path_url_add_component(basecoll_url, relative_url, pool);

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/client.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/client.c Tue Mar 16 18:03:37 2010
@@ -373,7 +373,16 @@ static svn_error_t *find_tunnel_agent(co
 
   /* We have one predefined tunnel scheme, if it isn't overridden by config. */
   if (!val && strcmp(tunnel, "ssh") == 0)
-    val = "$SVN_SSH ssh";
+    {
+      /* Killing the tunnel agent with SIGTERM leads to unsightly
+       * stderr output from ssh, unless we pass -q.
+       * The "-q" option to ssh is widely supported: all versions of
+       * OpenSSH have it, the old ssh-1.x and the 2.x, 3.x ssh.com
+       * versions have it too. If the user is using some other ssh
+       * implementation that doesn't accept it, they can override it
+       * in the [tunnels] section of the config. */
+      val = "$SVN_SSH ssh -q";
+    }
 
   if (!val || !*val)
     return svn_error_createf(SVN_ERR_BAD_URL, NULL,
@@ -448,6 +457,7 @@ static svn_error_t *make_tunnel(const ch
   apr_status_t status;
   apr_proc_t *proc;
   apr_procattr_t *attr;
+  svn_error_t *err;
 
   status = apr_procattr_create(&attr, pool);
   if (status == APR_SUCCESS)
@@ -462,6 +472,37 @@ static svn_error_t *make_tunnel(const ch
   if (status != APR_SUCCESS)
     return svn_error_wrap_apr(status, _("Can't create tunnel"));
 
+  /* Arrange for the tunnel agent to get a SIGTERM on pool
+   * cleanup.  This is a little extreme, but the alternatives
+   * weren't working out.
+   *
+   * Closing the pipes and waiting for the process to die
+   * was prone to mysterious hangs which are difficult to
+   * diagnose (e.g. svnserve dumps core due to unrelated bug;
+   * sshd goes into zombie state; ssh connection is never
+   * closed; ssh never terminates).
+   * See also the long dicussion in issue #2580 if you really
+   * want to know various reasons for these problems and
+   * the different opinions on this issue.
+   *
+   * On Win32, APR does not support KILL_ONLY_ONCE. It only has
+   * KILL_ALWAYS and KILL_NEVER. Other modes are converted to 
+   * KILL_ALWAYS, which immediately calls TerminateProcess().
+   * This instantly kills the tunnel, leaving sshd and svnserve
+   * on a remote machine running indefinitely. These processes
+   * accumulate. The problem is most often seen with a fast client
+   * machine and a modest internet connection, as the tunnel
+   * is killed before being able to gracefully complete the 
+   * session. In that case, svn is unusable 100% of the time on
+   * the windows machine. Thus, on Win32, we use KILL_NEVER and
+   * take the lesser of two evils.
+   */
+#ifdef WIN32
+  apr_pool_note_subprocess(pool, proc, APR_KILL_NEVER);
+#else
+  apr_pool_note_subprocess(pool, proc, APR_KILL_ONLY_ONCE);
+#endif
+
   /* APR pipe objects inherit by default.  But we don't want the
    * tunnel agent's pipes held open by future child processes
    * (such as other ra_svn sessions), so turn that off. */
@@ -470,7 +511,14 @@ static svn_error_t *make_tunnel(const ch
 
   /* Guard against dotfile output to stdout on the server. */
   *conn = svn_ra_svn_create_conn(NULL, proc->out, proc->in, pool);
-  SVN_ERR(svn_ra_svn_skip_leading_garbage(*conn, pool));
+  err = svn_ra_svn_skip_leading_garbage(*conn, pool);
+  if (err)
+    return svn_error_quick_wrap(
+             err,
+             _("To better debug SSH connection problems, remove the -q "
+               "option from 'ssh' in the [tunnels] section of your "
+               "Subversion configuration file."));
+
   return SVN_NO_ERROR;
 }
 
@@ -2202,6 +2250,7 @@ ra_svn_replay_range(svn_ra_session_t *se
   svn_ra_svn__session_baton_t *sess = session->priv;
   apr_pool_t *iterpool;
   svn_revnum_t rev;
+  svn_boolean_t drive_aborted = FALSE;
 
   SVN_ERR(svn_ra_svn_write_cmd(sess->conn, pool, "replay-range", "rrrb",
                                start_revision, end_revision,
@@ -2237,7 +2286,14 @@ ra_svn_replay_range(svn_ra_session_t *se
                             iterpool));
       SVN_ERR(svn_ra_svn_drive_editor2(sess->conn, iterpool,
                                        editor, edit_baton,
-                                       NULL, TRUE));
+                                       &drive_aborted, TRUE));
+      /* If drive_editor2() aborted the commit, do NOT try to call
+         revfinish_func and commit the transaction! */
+      if (drive_aborted) {
+        svn_pool_destroy(iterpool);
+        return svn_error_create(SVN_ERR_RA_SVN_IO_ERROR, NULL,
+                                _("Error while replaying commit"));
+      }
       SVN_ERR(revfinish_func(rev, replay_baton,
                              editor, edit_baton,
                              rev_props,

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/cyrus_auth.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/cyrus_auth.c Tue Mar 16 18:03:37 2010
@@ -351,10 +351,8 @@ static svn_error_t *new_sasl_ctx(sasl_co
                                 sasl_errdetail(*sasl_ctx));
     }
 
-  /* Set security properties. Don't allow PLAIN or LOGIN, since we
-     don't support TLS yet. */
+  /* Set security properties. */
   svn_ra_svn__default_secprops(&secprops);
-  secprops.security_flags = SASL_SEC_NOPLAINTEXT;
   sasl_setprop(*sasl_ctx, SASL_SEC_PROPS, &secprops);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/marshal.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_ra_svn/marshal.c Tue Mar 16 18:03:37 2010
@@ -997,17 +997,24 @@ svn_error_t *svn_ra_svn_write_cmd_respon
 svn_error_t *svn_ra_svn_write_cmd_failure(svn_ra_svn_conn_t *conn,
                                           apr_pool_t *pool, svn_error_t *err)
 {
+  char buffer[128];
   SVN_ERR(svn_ra_svn_start_list(conn, pool));
   SVN_ERR(svn_ra_svn_write_word(conn, pool, "failure"));
   SVN_ERR(svn_ra_svn_start_list(conn, pool));
   for (; err; err = err->child)
     {
+      const char *msg = err->message;
+
+      if (msg == NULL)
+        msg = svn_strerror(err->apr_err, buffer, sizeof(buffer));
+
       /* The message string should have been optional, but we can't
          easily change that, so marshal nonexistent messages as "". */
       SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "nccn",
                                      (apr_uint64_t) err->apr_err,
-                                     err->message ? err->message : "",
-                                     err->file, (apr_uint64_t) err->line));
+                                     msg ? msg : "",
+                                     err->file ? err->file : "",
+                                     (apr_uint64_t) err->line));
     }
   SVN_ERR(svn_ra_svn_end_list(conn, pool));
   SVN_ERR(svn_ra_svn_end_list(conn, pool));

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/dump.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/dump.c Tue Mar 16 18:03:37 2010
@@ -1213,6 +1213,7 @@ svn_repos_verify_fs(svn_repos_t *repos,
       const svn_delta_editor_t *cancel_editor;
       void *cancel_edit_baton;
       svn_fs_root_t *to_root;
+      apr_hash_t *props;
 
       svn_pool_clear(iterpool);
 
@@ -1234,6 +1235,7 @@ svn_repos_verify_fs(svn_repos_t *repos,
       SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
                                 cancel_editor, cancel_edit_baton,
                                 NULL, NULL, iterpool));
+      SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool));
       SVN_ERR(svn_stream_printf(feedback_stream, iterpool,
                                 _("* Verified revision %ld.\n"),
                                 rev));

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/load.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/load.c Tue Mar 16 18:03:37 2010
@@ -229,10 +229,20 @@ prefix_mergeinfo_paths(svn_string_t **me
   prefixed_mergeinfo = apr_hash_make(pool);
   for (hi = apr_hash_first(NULL, mergeinfo); hi; hi = apr_hash_next(hi))
     {
-      const char *path;
-      const void *merge_source;
-      apr_hash_this(hi, &merge_source, NULL, &rangelist);
-      path = svn_path_join(parent_dir, (const char*)merge_source+1, pool);
+      const void *key;
+      const char *path, *merge_source;
+
+      apr_hash_this(hi, &key, NULL, &rangelist);
+      merge_source = key;
+
+      /* The svn:mergeinfo property syntax demands absolute repository
+         paths, so prepend a leading slash if PARENT_DIR lacks one.  */
+      if (*parent_dir != '/')
+        path = svn_path_join_many(pool, "/", parent_dir, 
+                                  merge_source + 1, NULL);
+      else
+        path = svn_path_join(parent_dir, merge_source + 1, pool);
+
       apr_hash_set(prefixed_mergeinfo, path, APR_HASH_KEY_STRING, rangelist);
     }
   return svn_mergeinfo_to_string(mergeinfo_val, prefixed_mergeinfo, pool);

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/repos.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_repos/repos.c Tue Mar 16 18:03:37 2010
@@ -267,8 +267,8 @@ create_locks(svn_repos_t *repos, apr_poo
 #define PREWRITTEN_HOOKS_TEXT                                                 \
   "# For more examples and pre-written hooks, see those in"                NL \
   "# the Subversion repository at"                                         NL \
-  "# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and"        NL \
-  "# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/"          NL
+  "# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and"        NL \
+  "# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/"          NL
 
 
 static svn_error_t *

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/config_file.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/config_file.c Tue Mar 16 18:03:37 2010
@@ -502,7 +502,7 @@ svn_config_ensure(const char *config_dir
   if (! path)
     return SVN_NO_ERROR;
 
-  err = svn_io_check_path(path, &kind, pool);
+  err = svn_io_check_resolved_path(path, &kind, pool);
   if (err)
     {
       /* Don't throw an error, but don't continue. */
@@ -1009,7 +1009,7 @@ svn_config_ensure(const char *config_dir
         "### passed to the tunnel agent as <user>@<hostname>.)  If the"      NL
         "### built-in ssh scheme were not predefined, it could be defined"   NL
         "### as:"                                                            NL
-        "# ssh = $SVN_SSH ssh"                                               NL
+        "# ssh = $SVN_SSH ssh -q"                                            NL
         "### If you wanted to define a new 'rsh' scheme, to be used with"    NL
         "### 'svn+rsh:' URLs, you could do so as follows:"                   NL
         "# rsh = rsh"                                                        NL
@@ -1064,11 +1064,11 @@ svn_config_ensure(const char *config_dir
         "### 'enable-auto-props' option."                                    NL
         "# *.c = svn:eol-style=native"                                       NL
         "# *.cpp = svn:eol-style=native"                                     NL
-        "# *.h = svn:eol-style=native"                                       NL
+        "# *.h = svn:keywords=Author Date Id Rev URL;svn:eol-style=native"   NL
         "# *.dsp = svn:eol-style=CRLF"                                       NL
         "# *.dsw = svn:eol-style=CRLF"                                       NL
         "# *.sh = svn:eol-style=native;svn:executable"                       NL
-        "# *.txt = svn:eol-style=native"                                     NL
+        "# *.txt = svn:eol-style=native;svn:keywords=Author Date Id Rev URL;"NL
         "# *.png = svn:mime-type=image/png"                                  NL
         "# *.jpg = svn:mime-type=image/jpeg"                                 NL
         "# Makefile = svn:eol-style=native"                                  NL

Modified: subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/io.c?rev=923910&r1=923909&r2=923910&view=diff
==============================================================================
--- subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/1.6.x-issue3432/subversion/libsvn_subr/io.c Tue Mar 16 18:03:37 2010
@@ -1862,17 +1862,12 @@ svn_io_remove_dir(const char *path, apr_
 
  Similar problem has been observed on FreeBSD.
 
- See http://subversion.tigris.org/issues/show_bug.cgi?id=1896 for more
- discussion and an initial solution.
+ The workaround is to delete the files only _after_ the initial
+ directory scan.  A previous workaround involving rewinddir is
+ problematic on Win32 and some NFS clients, notably NetBSD.
 
- To work around the problem, we do a rewinddir after we delete all files
- and see if there's anything left. We repeat the steps untill there's
- nothing left to delete.
-
- This workaround causes issues on Windows where delete's are asynchronous,
- however, so we never rewind if we're on Windows (the delete says it is
- complete, we rewind, we see the same file and try to delete it again,
- we fail.
+ See http://subversion.tigris.org/issues/show_bug.cgi?id=1896 and
+ http://subversion.tigris.org/issues/show_bug.cgi?id=3501.
 */
 
 /* Neither windows nor unix allows us to delete a non-empty
@@ -1884,13 +1879,10 @@ svn_io_remove_dir2(const char *path, svn
                    svn_cancel_func_t cancel_func, void *cancel_baton,
                    apr_pool_t *pool)
 {
-  apr_status_t status;
-  apr_dir_t *this_dir;
-  apr_finfo_t this_entry;
+  svn_error_t *err;
   apr_pool_t *subpool;
-  apr_int32_t flags = APR_FINFO_TYPE | APR_FINFO_NAME;
-  const char *path_apr;
-  int need_rewind;
+  apr_hash_t *dirents;
+  apr_hash_index_t *ent;
 
   /* Check for pending cancellation request.
      If we need to bail out, do so early. */
@@ -1898,112 +1890,50 @@ svn_io_remove_dir2(const char *path, svn
   if (cancel_func)
     SVN_ERR((*cancel_func)(cancel_baton));
 
-  /* Convert path to native here and call apr_dir_open directly,
-     instead of just using svn_io_dir_open, because we're going to
-     need path_apr later anyway when we remove the dir itself. */
-
-  if (path[0] == '\0')
-    /* APR doesn't like "" directories; use "." instead. */
-    SVN_ERR(cstring_from_utf8(&path_apr, ".", pool));
-  else
-    SVN_ERR(cstring_from_utf8(&path_apr, path, pool));
+  subpool = svn_pool_create(pool);
 
-  status = apr_dir_open(&this_dir, path_apr, pool);
-  if (status)
+  err = svn_io_get_dirents2(&dirents, path, subpool);
+  if (err)
     {
       /* if the directory doesn't exist, our mission is accomplished */
-      if (ignore_enoent && APR_STATUS_IS_ENOENT(status))
-        return SVN_NO_ERROR;
-      else
-        return svn_error_wrap_apr(status,
-                                  _("Can't open directory '%s'"),
-                                  svn_path_local_style(path, pool));
+      if (ignore_enoent && APR_STATUS_IS_ENOENT(err->apr_err))
+	{
+	  svn_error_clear(err);
+	  return SVN_NO_ERROR;
+	}
+      return err;
     }
 
-  subpool = svn_pool_create(pool);
-
-  do
+  for (ent = apr_hash_first(subpool, dirents); ent; ent = apr_hash_next(ent))
     {
-      need_rewind = FALSE;
-
-      for (status = apr_dir_read(&this_entry, flags, this_dir);
-           status == APR_SUCCESS;
-           status = apr_dir_read(&this_entry, flags, this_dir))
+      const void *key;
+      void *val;
+      char *fullpath;
+
+      apr_hash_this(ent, &key, NULL, &val);
+      fullpath = svn_path_join(path, key, subpool);
+      if (((svn_io_dirent_t *)val)->kind == svn_node_dir)
         {
-          svn_pool_clear(subpool);
-          if ((this_entry.filetype == APR_DIR)
-              && ((this_entry.name[0] == '.')
-                  && ((this_entry.name[1] == '\0')
-                      || ((this_entry.name[1] == '.')
-                          && (this_entry.name[2] == '\0')))))
-            {
-              continue;
-            }
-          else  /* something other than "." or "..", so proceed */
-            {
-              const char *fullpath, *entry_utf8;
-
-#ifndef WIN32
-              need_rewind = TRUE;
-#endif
-
-              SVN_ERR(entry_name_to_utf8(&entry_utf8, this_entry.name,
-                                         path_apr, subpool));
-
-              fullpath = svn_path_join(path, entry_utf8, subpool);
-
-              if (this_entry.filetype == APR_DIR)
-                {
-                  /* Don't check for cancellation, the callee
-                     will immediately do so */
-                  SVN_ERR(svn_io_remove_dir2(fullpath, FALSE,
-                                             cancel_func, cancel_baton,
-                                             subpool));
-                }
-              else
-                {
-                  svn_error_t *err;
-
-                  if (cancel_func)
-                    SVN_ERR((*cancel_func)(cancel_baton));
-
-                  err = svn_io_remove_file(fullpath, subpool);
-                  if (err)
-                    return svn_error_createf
-                      (err->apr_err, err, _("Can't remove '%s'"),
-                       svn_path_local_style(fullpath, subpool));
-                }
-            }
+          /* Don't check for cancellation, the callee will immediately do so */
+          SVN_ERR(svn_io_remove_dir2(fullpath, FALSE, cancel_func,
+                                     cancel_baton, subpool));
         }
-
-      if (need_rewind)
+      else
         {
-          status = apr_dir_rewind(this_dir);
-          if (status)
-            return svn_error_wrap_apr(status, _("Can't rewind directory '%s'"),
-                                      svn_path_local_style (path, pool));
+          if (cancel_func)
+            SVN_ERR((*cancel_func)(cancel_baton));
+
+          err = svn_io_remove_file(fullpath, subpool);
+          if (err)
+            return svn_error_createf
+              (err->apr_err, err, _("Can't remove '%s'"),
+               svn_path_local_style(fullpath, subpool));
         }
     }
-  while (need_rewind);
 
   svn_pool_destroy(subpool);
 
-  if (!APR_STATUS_IS_ENOENT(status))
-    return svn_error_wrap_apr(status, _("Can't read directory '%s'"),
-                              svn_path_local_style(path, pool));
-
-  status = apr_dir_close(this_dir);
-  if (status)
-    return svn_error_wrap_apr(status, _("Error closing directory '%s'"),
-                              svn_path_local_style(path, pool));
-
-  status = apr_dir_remove(path_apr, pool);
-  WIN32_RETRY_LOOP(status, apr_dir_remove(path_apr, pool));
-  if (status)
-    return svn_error_wrap_apr(status, _("Can't remove '%s'"),
-                              svn_path_local_style(path, pool));
-
-  return APR_SUCCESS;
+  return svn_io_dir_remove_nonrecursive(path, pool);
 }
 
 svn_error_t *
@@ -2522,6 +2452,18 @@ svn_io_run_diff3_3(int *exitcode,
   return SVN_NO_ERROR;
 }
 
+
+/* Canonicalize a string for hashing.  Modifies KEY in place. */
+static APR_INLINE char *
+fileext_tolower(char *key)
+{
+  register char *p;
+  for (p = key; *p != 0; ++p)
+    *p = apr_tolower(*p);
+  return key;
+}
+
+
 svn_error_t *
 svn_io_parse_mimetypes_file(apr_hash_t **type_map,
                             const char *mimetypes_file,
@@ -2570,6 +2512,7 @@ svn_io_parse_mimetypes_file(apr_hash_t *
           for (i = 1; i < tokens->nelts; i++)
             {
               const char *ext = APR_ARRAY_IDX(tokens, i, const char *);
+              fileext_tolower((char *)ext);
               apr_hash_set(types, ext, APR_HASH_KEY_STRING, type);
             }
         }
@@ -2611,13 +2554,6 @@ svn_io_detect_mimetype2(const char **mim
   /* Default return value is NULL. */
   *mimetype = NULL;
 
-  /* See if this file even exists, and make sure it really is a file. */
-  SVN_ERR(svn_io_check_path(file, &kind, pool));
-  if (kind != svn_node_file)
-    return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
-                             _("Can't detect MIME type of non-file '%s'"),
-                             svn_path_local_style(file, pool));
-
   /* If there is a mimetype_map provided, we'll first try to look up
      our file's extension in the map.  Failing that, we'll run the
      heuristic. */
@@ -2625,6 +2561,7 @@ svn_io_detect_mimetype2(const char **mim
     {
       const char *type_from_map, *path_ext;
       svn_path_splitext(NULL, &path_ext, file, pool);
+      fileext_tolower((char *)path_ext);
       if ((type_from_map = apr_hash_get(mimetype_map, path_ext,
                                         APR_HASH_KEY_STRING)))
         {
@@ -2633,6 +2570,13 @@ svn_io_detect_mimetype2(const char **mim
         }
     }
 
+  /* See if this file even exists, and make sure it really is a file. */
+  SVN_ERR(svn_io_check_path(file, &kind, pool));
+  if (kind != svn_node_file)
+    return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
+                             _("Can't detect MIME type of non-file '%s'"),
+                             svn_path_local_style(file, pool));
+
   SVN_ERR(svn_io_file_open(&fh, file, APR_READ, 0, pool));
 
   /* Read a block of data from FILE. */