subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1066452 [4/11] - in /subversion/branches/performance: ./ build/ build/ac-macros/ build/generator/ contrib/hook-scripts/ notes/ notes/api-errata/1.7/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/include/ subvers...
Date Wed, 02 Feb 2011 13:04:59 GMT
Modified: subversion/branches/performance/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_diff/parse-diff.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/performance/subversion/libsvn_diff/parse-diff.c Wed Feb  2 13:04:51 2011
@@ -35,20 +35,33 @@
 #include "svn_diff.h"
 
 #include "private/svn_eol_private.h"
+#include "private/svn_dep_compat.h"
 
 /* Helper macro for readability */
 #define starts_with(str, start)  \
   (strncmp((str), (start), strlen(start)) == 0)
 
-struct svn_diff_hunk_t {
-  /* Hunk texts (see include/svn_diff.h). */
-  svn_stream_t *diff_text;
-  svn_stream_t *original_text;
-  svn_stream_t *modified_text;
+/* This struct describes a range within a file, as well as the
+ * current cursor position within the range. All numbers are in bytes. */
+struct svn_diff__hunk_range {
+  apr_off_t start;
+  apr_off_t end;
+  apr_off_t current;
+};
 
+struct svn_diff_hunk_t {
   /* The patch this hunk belongs to. */
   svn_patch_t *patch;
 
+  /* APR file handle to the patch file this hunk came from. */
+  apr_file_t *apr_file;
+
+  /* Ranges used to keep track of this hunk's texts positions within
+   * the patch file. */
+  struct svn_diff__hunk_range diff_text_range;
+  struct svn_diff__hunk_range original_text_range;
+  struct svn_diff__hunk_range modified_text_range;
+
   /* Hunk ranges as they appeared in the patch file.
    * All numbers are lines, not bytes. */
   svn_linenum_t original_start;
@@ -61,28 +74,28 @@ struct svn_diff_hunk_t {
   svn_linenum_t trailing_context;
 };
 
-svn_error_t *
-svn_diff_hunk_reset_diff_text(const svn_diff_hunk_t *hunk)
+void
+svn_diff_hunk_reset_diff_text(svn_diff_hunk_t *hunk)
 {
-  return svn_error_return(svn_stream_reset(hunk->diff_text));
+  hunk->diff_text_range.current = hunk->diff_text_range.start;
 }
 
-svn_error_t *
-svn_diff_hunk_reset_original_text(const svn_diff_hunk_t *hunk)
+void
+svn_diff_hunk_reset_original_text(svn_diff_hunk_t *hunk)
 {
   if (hunk->patch->reverse)
-    return svn_error_return(svn_stream_reset(hunk->modified_text));
+    hunk->modified_text_range.current = hunk->modified_text_range.start;
   else
-    return svn_error_return(svn_stream_reset(hunk->original_text));
+    hunk->original_text_range.current = hunk->original_text_range.start;
 }
 
-svn_error_t *
-svn_diff_hunk_reset_modified_text(const svn_diff_hunk_t *hunk)
+void
+svn_diff_hunk_reset_modified_text(svn_diff_hunk_t *hunk)
 {
   if (hunk->patch->reverse)
-    return svn_error_return(svn_stream_reset(hunk->original_text));
+    hunk->original_text_range.current = hunk->original_text_range.start;
   else
-    return svn_error_return(svn_stream_reset(hunk->modified_text));
+    hunk->modified_text_range.current = hunk->modified_text_range.start;
 }
 
 svn_linenum_t
@@ -253,32 +266,49 @@ parse_hunk_header(const char *header, sv
   return TRUE;
 }
 
-/* Set *EOL to the first end-of-line string found in the stream
- * accessed through READ_FN, MARK_FN and SEEK_FN, whose stream baton
- * is BATON.  Leave the stream read position unchanged.
+/* Set *EOL to the first end-of-line string found in FILE.
+ * Start scanning at the current file cursor offset and scan up
+ * to MAX_LEN bytes. Leave the current file cursor position unchanged.
  * Allocate *EOL statically; POOL is a scratch pool. */
 static svn_error_t *
-scan_eol(const char **eol, svn_stream_t *stream, apr_pool_t *pool)
+scan_eol(const char **eol, apr_file_t *file, apr_size_t max_len,
+         apr_pool_t *pool)
 {
   const char *eol_str;
-  svn_stream_mark_t *mark;
+  apr_off_t pos;
+  apr_size_t total_len;
 
-  SVN_ERR(svn_stream_mark(stream, &mark, pool));
+  pos = 0;
+  SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, pool));
 
   eol_str = NULL;
+  total_len = 0;
   while (! eol_str)
     {
-      char buf[512];
+      char buf[256];
       apr_size_t len;
+      svn_error_t *err;
+
+      if (total_len >= max_len)
+        break;
+
+      len = sizeof(buf) - 1 < (max_len - total_len) ? sizeof(buf) - 1
+                                                    : (max_len - total_len);
+      err = svn_io_file_read_full(file, buf, sizeof(buf) - 1, &len, pool);
+      if (err && APR_STATUS_IS_EOF(err->apr_err))
+        svn_error_clear(err);
+      else
+        SVN_ERR(err);
 
-      len = sizeof(buf);
-      SVN_ERR(svn_stream_read(stream, buf, &len));
       if (len == 0)
         break; /* EOF */
+
+      buf[len] = '\0';
+      total_len += len;
       eol_str = svn_eol__detect_eol(buf, buf + len);
     }
 
-  SVN_ERR(svn_stream_seek(stream, mark));
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, pool));
 
   *eol = eol_str;
 
@@ -286,95 +316,129 @@ scan_eol(const char **eol, svn_stream_t 
 }
 
 /* A helper function similar to svn_stream_readline_detect_eol(),
- * suitable for reading original or modified hunk text from a STREAM
- * which has been mapped onto a hunk region within a unidiff patch file.
- *
- * Allocate *STRINGBUF in RESULT_POOL, and read into it one line from STREAM.
+ * suitable for reading a line of text from a range in the patch file.
  *
- * STREAM is expected to contain unidiff text.
- * Leading unidiff symbols ('+', '-', and ' ') are removed from the line,
- * Any lines commencing with the VERBOTEN character are discarded.
- * VERBOTEN should be '+' or '-', depending on which form of hunk text
- * is being read.
+ * Allocate *STRINGBUF in RESULT_POOL, and read into it one line from FILE.
+ * Reading stops either after a line-terminator was found or after
+ * MAX_LEN bytes have been read.
  *
  * The line-terminator is detected automatically and stored in *EOL
- * if EOL is not NULL. If EOF is reached and the stream does not end
+ * if EOL is not NULL. If EOF is reached and FILE does not end
  * with a newline character, and EOL is not NULL, *EOL is set to NULL.
  *
  * SCRATCH_POOL is used for temporary allocations.
  */
 static svn_error_t *
-hunk_readline(svn_stream_t *stream,
-              svn_stringbuf_t **stringbuf,
-              const char **eol,
-              svn_boolean_t *eof,
-              char verboten,
-              apr_pool_t *result_pool,
-              apr_pool_t *scratch_pool)
+readline(apr_file_t *file,
+         svn_stringbuf_t **stringbuf,
+         const char **eol,
+         svn_boolean_t *eof,
+         apr_size_t max_len,
+         apr_pool_t *result_pool,
+         apr_pool_t *scratch_pool)
 {
   svn_stringbuf_t *str;
-  apr_pool_t *iterpool;
-  svn_boolean_t filtered;
   const char *eol_str;
+  apr_size_t numbytes;
+  const char *match;
+  char c;
+  apr_size_t len;
+
+  str = svn_stringbuf_create_ensure(80, result_pool);
+
+  SVN_ERR(scan_eol(&eol_str, file, max_len, scratch_pool));
+  if (eol)
+    *eol = eol_str;
+  if (eol_str == NULL)
+    {
+      /* No newline until EOF, EOL_STR can be anything. */
+      eol_str = APR_EOL_STR;
+    }
+
+  /* Read into STR up to and including the next EOL sequence. */
+  match = eol_str;
+  numbytes = 1;
+  len = 0;
+  while (*match)
+    {
+      svn_error_t *err;
+
+      err = svn_io_file_read_full(file, &c, sizeof(c), &numbytes,
+                                  scratch_pool);
+      if (err && APR_STATUS_IS_EOF(err->apr_err))
+        svn_error_clear(err);
+      else
+        SVN_ERR(err);
+      len++;
+      if (numbytes != 1 || len > max_len)
+        {
+          *eof = TRUE;
+          *stringbuf = str;
+          return SVN_NO_ERROR;
+        }
+      if (c == *match)
+        match++;
+      else
+        match = eol_str;
 
-  *eof = FALSE;
+      svn_stringbuf_appendbyte(str, c);
+    }
 
-  iterpool = svn_pool_create(scratch_pool);
-  do
-    {
-      apr_size_t numbytes;
-      const char *match;
-      char c;
+  *eof = FALSE;
+  svn_stringbuf_chop(str, match - eol_str);
+  *stringbuf = str;
 
-      svn_pool_clear(iterpool);
+  return SVN_NO_ERROR;
+}
 
-      /* Since we're reading one character at a time, let's at least
-         optimize for the 90% case.  90% of the time, we can avoid the
-         stringbuf ever having to realloc() itself if we start it out at
-         80 chars.  */
-      str = svn_stringbuf_create_ensure(80, iterpool);
+/* Read a line of original or modified hunk text from the specified
+ * RANGE within FILE. FILE is expected to contain unidiff text.
+ * Leading unidiff symbols ('+', '-', and ' ') are removed from the line,
+ * Any lines commencing with the VERBOTEN character are discarded.
+ * VERBOTEN should be '+' or '-', depending on which form of hunk text
+ * is being read.
+ * 
+ * All other parameters are as in svn_diff_hunk_readline_original_text()
+ * and svn_diff_hunk_readline_modified_text().
+ */
+static svn_error_t *
+hunk_readline_original_or_modified(apr_file_t *file,
+                                   struct svn_diff__hunk_range *range,
+                                   svn_stringbuf_t **stringbuf,
+                                   const char **eol,
+                                   svn_boolean_t *eof,
+                                   char verboten,
+                                   apr_pool_t *result_pool,
+                                   apr_pool_t *scratch_pool)
+{
+  apr_size_t max_len;
+  svn_boolean_t filtered;
+  apr_off_t pos;
+  svn_stringbuf_t *str;
 
-      SVN_ERR(scan_eol(&eol_str, stream, iterpool));
+  if (range->current >= range->end)
+    {
+      /* We're past the range. Indicate that no bytes can be read. */
+      *eof = TRUE;
       if (eol)
-        *eol = eol_str;
-      if (eol_str == NULL)
-        {
-          /* No newline until EOF, EOL_STR can be anything. */
-          eol_str = APR_EOL_STR;
-        }
-
-      /* Read into STR up to and including the next EOL sequence. */
-      match = eol_str;
-      numbytes = 1;
-      while (*match)
-        {
-          SVN_ERR(svn_stream_read(stream, &c, &numbytes));
-          if (numbytes != 1)
-            {
-              /* a 'short' read means the stream has run out. */
-              *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_str;
-              /* Process this short (or empty) line just like any other
-               * except with *EOF set. */
-              break;
-            }
-
-          if (c == *match)
-            match++;
-          else
-            match = eol_str;
-
-          svn_stringbuf_appendbyte(str, c);
-        }
+        *eol = NULL;
+      *stringbuf = svn_stringbuf_create("", result_pool);
+      return SVN_NO_ERROR;
+    }
 
-      svn_stringbuf_chop(str, match - eol_str);
+  pos = 0;
+  SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos,  scratch_pool));
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &range->current, scratch_pool));
+  do
+    {
+      max_len = range->end - range->current;
+      SVN_ERR(readline(file, &str, eol, eof, max_len,
+                       result_pool, scratch_pool));
+      range->current = 0;
+      SVN_ERR(svn_io_file_seek(file, APR_CUR, &range->current, scratch_pool));
       filtered = (str->data[0] == verboten || str->data[0] == '\\');
     }
   while (filtered && ! *eof);
-  /* Not destroying the iterpool just yet since we still need STR
-   * which is allocated in it. */
 
   if (filtered)
     {
@@ -392,46 +456,49 @@ hunk_readline(svn_stream_t *stream,
       *stringbuf = svn_stringbuf_dup(str, result_pool);
     }
 
-  /* Done. RIP iterpool. */
-  svn_pool_destroy(iterpool);
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_diff_hunk_readline_original_text(const svn_diff_hunk_t *hunk,
+svn_diff_hunk_readline_original_text(svn_diff_hunk_t *hunk,
                                      svn_stringbuf_t **stringbuf,
                                      const char **eol,
                                      svn_boolean_t *eof,
                                      apr_pool_t *result_pool,
                                      apr_pool_t *scratch_pool)
 {
-  return svn_error_return(hunk_readline(hunk->patch->reverse ?
-                                          hunk->modified_text :
-                                          hunk->original_text,
-                                        stringbuf, eol, eof,
-                                        hunk->patch->reverse ? '-' : '+',
-                                        result_pool, scratch_pool));
+  return svn_error_return(
+    hunk_readline_original_or_modified(hunk->apr_file,
+                                       hunk->patch->reverse ?
+                                         &hunk->modified_text_range :
+                                         &hunk->original_text_range,
+                                       stringbuf, eol, eof,
+                                       hunk->patch->reverse ? '-' : '+',
+                                       result_pool, scratch_pool));
 }
 
 svn_error_t *
-svn_diff_hunk_readline_modified_text(const svn_diff_hunk_t *hunk,
+svn_diff_hunk_readline_modified_text(svn_diff_hunk_t *hunk,
                                      svn_stringbuf_t **stringbuf,
                                      const char **eol,
                                      svn_boolean_t *eof,
                                      apr_pool_t *result_pool,
                                      apr_pool_t *scratch_pool)
 {
-  return svn_error_return(hunk_readline(hunk->patch->reverse ?
-                                          hunk->original_text :
-                                          hunk->modified_text,
-                                        stringbuf, eol, eof,
-                                        hunk->patch->reverse ? '+' : '-',
-                                        result_pool, scratch_pool));
+  return svn_error_return(
+    hunk_readline_original_or_modified(hunk->apr_file,
+                                       hunk->patch->reverse ?
+                                         &hunk->original_text_range :
+                                         &hunk->modified_text_range,
+                                       stringbuf, eol, eof,
+                                       hunk->patch->reverse ? '+' : '-',
+                                       result_pool, scratch_pool));
 }
 
 svn_error_t *
-svn_diff_hunk_readline_diff_text(const svn_diff_hunk_t *hunk,
+svn_diff_hunk_readline_diff_text(svn_diff_hunk_t *hunk,
                                  svn_stringbuf_t **stringbuf,
                                  const char **eol,
                                  svn_boolean_t *eof,
@@ -440,31 +507,52 @@ svn_diff_hunk_readline_diff_text(const s
 {
   svn_diff_hunk_t dummy;
   svn_stringbuf_t *line;
+  apr_size_t max_len;
+  apr_off_t pos;
 
-  SVN_ERR(svn_stream_readline_detect_eol(hunk->diff_text, &line, eol, eof,
-                                         result_pool));
+  if (hunk->diff_text_range.current >= hunk->diff_text_range.end)
+    {
+      /* We're past the range. Indicate that no bytes can be read. */
+      *eof = TRUE;
+      if (eol)
+        *eol = NULL;
+      *stringbuf = svn_stringbuf_create("", result_pool);
+      return SVN_NO_ERROR;
+    }
 
+  pos = 0;
+  SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR, &pos, scratch_pool));
+  SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET,
+                           &hunk->diff_text_range.current, scratch_pool));
+  max_len = hunk->diff_text_range.end - hunk->diff_text_range.current;
+  SVN_ERR(readline(hunk->apr_file, &line, eol, eof, max_len, result_pool,
+                   scratch_pool));
+  hunk->diff_text_range.current = 0;
+  SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR,
+                           &hunk->diff_text_range.current, scratch_pool));
+  SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &pos, scratch_pool));
+  
   if (hunk->patch->reverse)
     {
       if (parse_hunk_header(line->data, &dummy, "@@", scratch_pool))
         {
           /* Line is a hunk header, reverse it. */
-          *stringbuf = svn_stringbuf_createf(result_pool,
-                                             "@@ -%lu,%lu +%lu,%lu @@",
-                                             hunk->modified_start,
-                                             hunk->modified_length,
-                                             hunk->original_start,
-                                             hunk->original_length);
+          line = svn_stringbuf_createf(result_pool,
+                                       "@@ -%lu,%lu +%lu,%lu @@",
+                                       hunk->modified_start,
+                                       hunk->modified_length,
+                                       hunk->original_start,
+                                       hunk->original_length);
         }
       else if (parse_hunk_header(line->data, &dummy, "##", scratch_pool))
         {
           /* Line is a hunk header, reverse it. */
-          *stringbuf = svn_stringbuf_createf(result_pool,
-                                             "## -%lu,%lu +%lu,%lu ##",
-                                             hunk->modified_start,
-                                             hunk->modified_length,
-                                             hunk->original_start,
-                                             hunk->original_length);
+          line = svn_stringbuf_createf(result_pool,
+                                       "## -%lu,%lu +%lu,%lu ##",
+                                       hunk->modified_start,
+                                       hunk->modified_length,
+                                       hunk->original_start,
+                                       hunk->original_length);
         }
       else
         {
@@ -472,12 +560,10 @@ svn_diff_hunk_readline_diff_text(const s
             line->data[0] = '-';
           else if (line->data[0] == '-')
             line->data[0] = '+';
-
-          *stringbuf = line;
         }
     }
-  else
-    *stringbuf = line;
+
+  *stringbuf = line;
 
   return SVN_NO_ERROR;
 }
@@ -504,21 +590,21 @@ parse_prop_name(const char **prop_name, 
   return SVN_NO_ERROR;
 }
 
-/* Return the next *HUNK from a PATCH, using STREAM to read data
- * from the patch file. If no hunk can be found, set *HUNK to NULL. Set
- * IS_PROPERTY to TRUE if we have a property hunk. If the returned HUNK is
- * the first belonging to a certain property, then PROP_NAME and
+/* Return the next *HUNK from a PATCH in APR_FILE.
+ * If no hunk can be found, set *HUNK to NULL.
+ * Set IS_PROPERTY to TRUE if we have a property hunk. If the returned HUNK
+ * is the first belonging to a certain property, then PROP_NAME and
  * PROP_OPERATION will be set too. If we have a text hunk, PROP_NAME will be
- * NULL. If IGNORE_WHITESPACE is TRUE, let lines without leading spaces be
- * recognized as context lines.  Allocate results in
- * RESULT_POOL.  Use SCRATCH_POOL for all other allocations. */
+ * NULL.  If IGNORE_WHITESPACE is TRUE, lines without leading spaces will be
+ * treated as context lines.  Allocate results in RESULT_POOL.
+ * Use SCRATCH_POOL for all other allocations. */
 static svn_error_t *
 parse_next_hunk(svn_diff_hunk_t **hunk,
                 svn_boolean_t *is_property,
                 const char **prop_name,
                 svn_diff_operation_kind_t *prop_operation,
                 svn_patch_t *patch,
-                svn_stream_t *stream,
+                apr_file_t *apr_file,
                 svn_boolean_t ignore_whitespace,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
@@ -530,9 +616,6 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   svn_boolean_t eof, in_hunk, hunk_seen;
   apr_off_t pos, last_line;
   apr_off_t start, end;
-  svn_stream_t *diff_text;
-  svn_stream_t *original_text;
-  svn_stream_t *modified_text;
   svn_linenum_t original_lines;
   svn_linenum_t modified_lines;
   svn_linenum_t leading_context;
@@ -546,7 +629,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   *prop_name = NULL;
   *is_property = FALSE;
 
-  if (apr_file_eof(patch->patch_file) == APR_EOF)
+  if (apr_file_eof(apr_file) == APR_EOF)
     {
       /* No more hunks here. */
       *hunk = NULL;
@@ -562,7 +645,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
 
   /* Get current seek position -- APR has no ftell() :( */
   pos = 0;
-  SVN_ERR(svn_io_file_seek(patch->patch_file, APR_CUR, &pos, scratch_pool));
+  SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, scratch_pool));
 
   iterpool = svn_pool_create(scratch_pool);
   do
@@ -572,15 +655,14 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
 
       /* Remember the current line's offset, and read the line. */
       last_line = pos;
-      SVN_ERR(svn_stream_readline_detect_eol(stream, &line, NULL, &eof,
-                                             iterpool));
+      SVN_ERR(readline(apr_file, &line, NULL, &eof, APR_SIZE_MAX,
+                       iterpool, iterpool));
 
       if (! eof)
         {
-          /* Update line offset for next iteration.
-           * APR has no ftell() :( */
+          /* Update line offset for next iteration. */
           pos = 0;
-          SVN_ERR(svn_io_file_seek(patch->patch_file, APR_CUR, &pos, iterpool));
+          SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool));
         }
 
       /* Lines starting with a backslash are comments, such as
@@ -603,10 +685,9 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
 
           c = line->data[0];
           /* Tolerate chopped leading spaces on empty lines. */
-          if (original_lines > 0 && modified_lines > 0
-              && ((c == ' ')
-              || (! eof && line->len == 0)
-              || (ignore_whitespace && c != del && c != add)))
+          if (original_lines > 0 && modified_lines > 0 &&
+              ((c == ' ') || (! eof && line->len == 0) ||
+               (ignore_whitespace && c != del && c != add)))
             {
               hunk_seen = TRUE;
               original_lines--;
@@ -653,9 +734,6 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
         }
       else
         {
-          /* ### Add an is_hunk_header() helper function that returns
-           * ### the proper atat string? Then we could collapse the
-           * ### following two if-clauses. */
           if (starts_with(line->data, text_atat))
             {
               /* Looks like we have a hunk header, try to rip it apart. */
@@ -717,41 +795,23 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
     /* Rewind to the start of the line just read, so subsequent calls
      * to this function or svn_diff_parse_next_patch() don't end
      * up skipping the line -- it may contain a patch or hunk header. */
-    SVN_ERR(svn_io_file_seek(patch->patch_file, APR_SET, &last_line,
-                             scratch_pool));
+    SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &last_line, scratch_pool));
 
   if (hunk_seen && start < end)
     {
-      apr_file_t *f;
-      apr_int32_t flags = APR_READ | APR_BUFFERED;
-
-      /* Create a stream which returns the hunk text itself. */
-      SVN_ERR(svn_io_file_open(&f, patch->path, flags, APR_OS_DEFAULT,
-                               result_pool));
-      diff_text = svn_stream_from_aprfile_range_readonly(f, FALSE,
-                                                         start, end,
-                                                         result_pool);
-
-      /* Create a stream which returns the original hunk text. */
-      SVN_ERR(svn_io_file_open(&f, patch->path, flags, APR_OS_DEFAULT,
-                               result_pool));
-      original_text = svn_stream_from_aprfile_range_readonly(f, FALSE,
-                                                             start, end,
-                                                             result_pool);
-
-      /* Create a stream which returns the modified hunk text. */
-      SVN_ERR(svn_io_file_open(&f, patch->path, flags, APR_OS_DEFAULT,
-                               result_pool));
-      modified_text = svn_stream_from_aprfile_range_readonly(f, FALSE,
-                                                             start, end,
-                                                             result_pool);
-
-      (*hunk)->diff_text = diff_text;
       (*hunk)->patch = patch;
-      (*hunk)->original_text = original_text;
-      (*hunk)->modified_text = modified_text;
+      (*hunk)->apr_file = apr_file;
       (*hunk)->leading_context = leading_context;
       (*hunk)->trailing_context = trailing_context;
+      (*hunk)->diff_text_range.start = start;
+      (*hunk)->diff_text_range.current = start;
+      (*hunk)->diff_text_range.end = end;
+      (*hunk)->original_text_range.start = start;
+      (*hunk)->original_text_range.current = start;
+      (*hunk)->original_text_range.end = end;
+      (*hunk)->modified_text_range.start = start;
+      (*hunk)->modified_text_range.current = start;
+      (*hunk)->modified_text_range.end = end;
     }
   else
     /* Something went wrong, just discard the result. */
@@ -775,18 +835,6 @@ compare_hunks(const void *a, const void 
   return 0;
 }
 
-/*
- * Ensure that all streams which were opened for HUNK are closed.
- */
-static svn_error_t *
-close_hunk(const svn_diff_hunk_t *hunk)
-{
-  SVN_ERR(svn_stream_close(hunk->original_text));
-  SVN_ERR(svn_stream_close(hunk->modified_text));
-  SVN_ERR(svn_stream_close(hunk->diff_text));
-  return SVN_NO_ERROR;
-}
-
 /* Possible states of the diff header parser. */
 enum parse_state
 {
@@ -1134,70 +1182,131 @@ add_property_hunk(svn_patch_t *patch, co
   return SVN_NO_ERROR;
 }
 
+struct svn_patch_file_t
+{
+  /* The APR file handle to the patch file. */
+  apr_file_t *apr_file;
+
+  /* The file offset at which the next patch is expected. */
+  apr_off_t next_patch_offset;
+};
+
+svn_error_t *
+svn_diff_open_patch_file(svn_patch_file_t **patch_file,
+                         const char *local_abspath,
+                         apr_pool_t *result_pool)
+{
+  svn_patch_file_t *p;
+
+  p = apr_palloc(result_pool, sizeof(*p));
+  SVN_ERR(svn_io_file_open(&p->apr_file, local_abspath,
+                           APR_READ | APR_BINARY, 0, result_pool));
+  p->next_patch_offset = 0;
+  *patch_file = p;
+
+  return SVN_NO_ERROR;
+}
+
+/* Parse hunks from APR_FILE and store them in PATCH->HUNKS.
+ * Parsing stops if no valid next hunk can be found.
+ * If IGNORE_WHITESPACE is TRUE, lines without
+ * leading spaces will be treated as context lines.
+ * Allocate results in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+parse_hunks(svn_patch_t *patch, apr_file_t *apr_file,
+            svn_boolean_t ignore_whitespace,
+            apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  svn_diff_hunk_t *hunk;
+  svn_boolean_t is_property;
+  const char *last_prop_name;
+  const char *prop_name;
+  svn_diff_operation_kind_t prop_operation;
+  apr_pool_t *iterpool;
+
+  last_prop_name = NULL;
+
+  patch->hunks = apr_array_make(result_pool, 10, sizeof(svn_diff_hunk_t *));
+  patch->prop_patches = apr_hash_make(result_pool);
+  iterpool = svn_pool_create(scratch_pool);
+  do
+    {
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(parse_next_hunk(&hunk, &is_property, &prop_name, &prop_operation,
+                              patch, apr_file, ignore_whitespace, result_pool,
+                              iterpool));
+
+      if (hunk && is_property)
+        {
+          if (! prop_name)
+            prop_name = last_prop_name;
+          else
+            last_prop_name = prop_name;
+          SVN_ERR(add_property_hunk(patch, prop_name, hunk, prop_operation,
+                                    result_pool));
+        }
+      else if (hunk)
+        {
+          APR_ARRAY_PUSH(patch->hunks, svn_diff_hunk_t *) = hunk;
+          last_prop_name = NULL;
+        }
+
+    }
+  while (hunk);
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* State machine for the diff header parser.
+ * Expected Input   Required state          Function to call */
+static struct transition transitions[] =
+{
+  {"--- ",          state_start,            diff_minus},
+  {"+++ ",          state_minus_seen,       diff_plus},
+  {"diff --git",    state_start,            git_start},
+  {"--- a/",        state_git_diff_seen,    git_minus},
+  {"--- a/",        state_git_tree_seen,    git_minus},
+  {"--- /dev/null", state_git_tree_seen,    git_minus},
+  {"+++ b/",        state_git_minus_seen,   git_plus},
+  {"+++ /dev/null", state_git_minus_seen,   git_plus},
+  {"rename from ",  state_git_diff_seen,    git_move_from},
+  {"rename to ",    state_move_from_seen,   git_move_to},
+  {"copy from ",    state_git_diff_seen,    git_copy_from},
+  {"copy to ",      state_copy_from_seen,   git_copy_to},
+  {"new file ",     state_git_diff_seen,    git_new_file},
+  {"deleted file ", state_git_diff_seen,    git_deleted_file},
+};
+
 svn_error_t *
 svn_diff_parse_next_patch(svn_patch_t **patch,
-                          apr_file_t *patch_file,
+                          svn_patch_file_t *patch_file,
                           svn_boolean_t reverse,
                           svn_boolean_t ignore_whitespace,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
-  const char *fname;
-  svn_stream_t *stream;
   apr_off_t pos, last_line;
   svn_boolean_t eof;
   svn_boolean_t line_after_tree_header_read = FALSE;
-
   apr_pool_t *iterpool;
-
   enum parse_state state = state_start;
 
-  /* Our table consisting of:
-   * Expected Input     Required state          Function to call */
-  struct transition transitions[] =
-    {
-      {"--- ",          state_start,            diff_minus},
-      {"+++ ",          state_minus_seen,       diff_plus},
-      {"diff --git",    state_start,            git_start},
-      {"--- a/",        state_git_diff_seen,    git_minus},
-      {"--- a/",        state_git_tree_seen,    git_minus},
-      {"--- /dev/null", state_git_tree_seen,    git_minus},
-      {"+++ b/",        state_git_minus_seen,   git_plus},
-      {"+++ /dev/null", state_git_minus_seen,   git_plus},
-      {"rename from ",  state_git_diff_seen,    git_move_from},
-      {"rename to ",    state_move_from_seen,   git_move_to},
-      {"copy from ",    state_git_diff_seen,    git_copy_from},
-      {"copy to ",      state_copy_from_seen,   git_copy_to},
-      {"new file ",     state_git_diff_seen,    git_new_file},
-      {"deleted file ", state_git_diff_seen,    git_deleted_file},
-    };
-
-  if (apr_file_eof(patch_file) == APR_EOF)
+  if (apr_file_eof(patch_file->apr_file) == APR_EOF)
     {
       /* No more patches here. */
       *patch = NULL;
       return SVN_NO_ERROR;
     }
 
-  /* Get the patch's filename. */
-  SVN_ERR(svn_io_file_name_get(&fname, patch_file, result_pool));
-
-  /* Record what we already know about the patch. */
   *patch = apr_pcalloc(result_pool, sizeof(**patch));
-  (*patch)->patch_file = patch_file;
-  (*patch)->path = fname;
 
-  /* Get a stream to read lines from the patch file.
-   * The file should not be closed when we close the stream so
-   * make sure it is disowned. */
-  stream = svn_stream_from_aprfile2(patch_file, TRUE, scratch_pool);
-
-  /* Get current seek position -- APR has no ftell() :( */
-  pos = 0;
-  SVN_ERR(svn_io_file_seek((*patch)->patch_file, APR_CUR, &pos, scratch_pool));
+  pos = patch_file->next_patch_offset;
+  SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &pos, scratch_pool));
 
   iterpool = svn_pool_create(scratch_pool);
-
   do
     {
       svn_stringbuf_t *line;
@@ -1207,15 +1316,15 @@ svn_diff_parse_next_patch(svn_patch_t **
 
       /* Remember the current line's offset, and read the line. */
       last_line = pos;
-      SVN_ERR(svn_stream_readline_detect_eol(stream, &line, NULL, &eof,
-                                             iterpool));
+      SVN_ERR(readline(patch_file->apr_file, &line, NULL, &eof,
+                       APR_SIZE_MAX, iterpool, iterpool));
 
       if (! eof)
         {
-          /* Update line offset for next iteration.
-           * APR has no ftell() :( */
+          /* Update line offset for next iteration. */
           pos = 0;
-          SVN_ERR(svn_io_file_seek((*patch)->patch_file, APR_CUR, &pos, iterpool));
+          SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_CUR, &pos,
+                                   iterpool));
         }
 
       /* Run the state machine. */
@@ -1231,27 +1340,26 @@ svn_diff_parse_next_patch(svn_patch_t **
             }
         }
 
-      if (state == state_unidiff_found
-          || state == state_git_header_found)
+      if (state == state_unidiff_found || state == state_git_header_found)
         {
           /* We have a valid diff header, yay! */
           break;
         }
-      else if (state == state_git_tree_seen
-               && line_after_tree_header_read)
+      else if (state == state_git_tree_seen && line_after_tree_header_read)
         {
           /* We have a valid diff header for a patch with only tree changes.
            * Rewind to the start of the line just read, so subsequent calls
            * to this function don't end up skipping the line -- it may
            * contain a patch. */
-          SVN_ERR(svn_io_file_seek((*patch)->patch_file, APR_SET, &last_line,
+          SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line,
                                    scratch_pool));
           break;
         }
       else if (state == state_git_tree_seen)
-          line_after_tree_header_read = TRUE;
+        line_after_tree_header_read = TRUE;
 
-    } while (! eof);
+    }
+  while (! eof);
 
   (*patch)->reverse = reverse;
   if (reverse)
@@ -1268,49 +1376,14 @@ svn_diff_parse_next_patch(svn_patch_t **
       *patch = NULL;
     }
   else
-    {
-      svn_diff_hunk_t *hunk;
-      svn_boolean_t is_property;
-      const char *last_prop_name;
-      const char *prop_name;
-      svn_diff_operation_kind_t prop_operation;
-
-      last_prop_name = NULL;
-
-      /* Parse hunks. */
-      (*patch)->hunks = apr_array_make(result_pool, 10,
-                                       sizeof(svn_diff_hunk_t *));
-      (*patch)->prop_patches = apr_hash_make(result_pool);
-      do
-        {
-          svn_pool_clear(iterpool);
-
-          SVN_ERR(parse_next_hunk(&hunk, &is_property, &prop_name,
-                                  &prop_operation, *patch, stream,
-                                  ignore_whitespace,
-                                  result_pool, iterpool));
-
-          if (hunk && is_property)
-            {
-              if (! prop_name)
-                prop_name = last_prop_name;
-              else
-                last_prop_name = prop_name;
-              SVN_ERR(add_property_hunk(*patch, prop_name, hunk, prop_operation,
-                                        result_pool));
-            }
-          else if (hunk)
-            {
-              APR_ARRAY_PUSH((*patch)->hunks, svn_diff_hunk_t *) = hunk;
-              last_prop_name = NULL;
-            }
-
-        }
-      while (hunk);
-    }
+    SVN_ERR(parse_hunks(*patch, patch_file->apr_file, ignore_whitespace,
+                        result_pool, iterpool));
 
   svn_pool_destroy(iterpool);
-  SVN_ERR(svn_stream_close(stream));
+
+  patch_file->next_patch_offset = 0;
+  SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_CUR,
+                           &patch_file->next_patch_offset, scratch_pool));
 
   if (*patch)
     {
@@ -1326,34 +1399,9 @@ svn_diff_parse_next_patch(svn_patch_t **
 }
 
 svn_error_t *
-svn_diff_close_patch(const svn_patch_t *patch, apr_pool_t *scratch_pool)
+svn_diff_close_patch_file(svn_patch_file_t *patch_file,
+                          apr_pool_t *scratch_pool)
 {
-  int i;
-  apr_hash_index_t *hi;
-
-  for (i = 0; i < patch->hunks->nelts; i++)
-    {
-      const svn_diff_hunk_t *hunk = APR_ARRAY_IDX(patch->hunks, i,
-                                                  svn_diff_hunk_t *);
-      SVN_ERR(close_hunk(hunk));
-    }
-
-  for (hi = apr_hash_first(scratch_pool, patch->prop_patches);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-          svn_prop_patch_t *prop_patch;
-
-          prop_patch = svn__apr_hash_index_val(hi);
-
-          for (i = 0; i < prop_patch->hunks->nelts; i++)
-            {
-              const svn_diff_hunk_t *hunk;
-
-              hunk = APR_ARRAY_IDX(prop_patch->hunks, i, svn_diff_hunk_t *);
-              SVN_ERR(close_hunk(hunk));
-            }
-    }
-
-  return SVN_NO_ERROR;
+  return svn_error_return(svn_io_file_close(patch_file->apr_file,
+                                            scratch_pool));
 }

Modified: subversion/branches/performance/subversion/libsvn_diff/token.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_diff/token.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_diff/token.c (original)
+++ subversion/branches/performance/subversion/libsvn_diff/token.c Wed Feb  2 13:04:51 2011
@@ -69,10 +69,10 @@ svn_diff__tree_create(svn_diff__tree_t *
 
 
 static svn_error_t *
-svn_diff__tree_insert_token(svn_diff__node_t **node, svn_diff__tree_t *tree,
-                            void *diff_baton,
-                            const svn_diff_fns_t *vtable,
-                            apr_uint32_t hash, void *token)
+tree_insert_token(svn_diff__node_t **node, svn_diff__tree_t *tree,
+                  void *diff_baton,
+                  const svn_diff_fns_t *vtable,
+                  apr_uint32_t hash, void *token)
 {
   svn_diff__node_t *new_node;
   svn_diff__node_t **node_ref;
@@ -165,9 +165,7 @@ svn_diff__get_tokens(svn_diff__position_
         break;
 
       offset++;
-      SVN_ERR(svn_diff__tree_insert_token(&node, tree,
-                                          diff_baton, vtable,
-                                          hash, token));
+      SVN_ERR(tree_insert_token(&node, tree, diff_baton, vtable, hash, token));
 
       /* Create a new position */
       position = apr_palloc(pool, sizeof(*position));

Modified: subversion/branches/performance/subversion/libsvn_fs_base/bdb/changes-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/bdb/changes-table.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/bdb/changes-table.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/bdb/changes-table.c Wed Feb  2 13:04:51 2011
@@ -39,6 +39,7 @@
 #include "changes-table.h"
 
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 
@@ -331,7 +332,7 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
                 continue;
 
               /* If we come across a child of our path, remove it. */
-              if (svn_uri_is_child(change->path, hashkey, subpool))
+              if (svn_fspath__is_child(change->path, hashkey, subpool))
                 apr_hash_set(changes, hashkey, klen, NULL);
             }
         }

Modified: subversion/branches/performance/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/bdb/env.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/bdb/env.c Wed Feb  2 13:04:51 2011
@@ -373,7 +373,7 @@ clear_cache(void *data)
 }
 #endif /* APR_HAS_THREADS */
 
-static volatile svn_atomic_t bdb_cache_state;
+static volatile svn_atomic_t bdb_cache_state = 0;
 
 static svn_error_t *
 bdb_init_cb(void *baton, apr_pool_t *pool)

Modified: subversion/branches/performance/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/bdb/locks-table.c Wed Feb  2 13:04:51 2011
@@ -39,6 +39,7 @@
 #include "lock-tokens-table.h"
 
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 
 
 int
@@ -249,8 +250,9 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
 
   /* As long as the prefix of the returned KEY matches LOOKUP_PATH we
      know it is either LOOKUP_PATH or a decendant thereof.  */
-  if (strcmp(path, "/") != 0)
+  if (!svn_fspath__is_root(path, strlen(path)))
     lookup_path = apr_pstrcat(pool, path, "/", (char *)NULL);
+
   while ((! db_err)
          && strncmp(lookup_path, key.data, strlen(lookup_path)) == 0)
     {
@@ -272,8 +274,8 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
              same set of results.  So just see if CHILD_PATH is an
              immediate child of PATH.  If not, we don't care about
              this item.   */
-          const char *rel_uri = svn_uri_is_child(path, child_path, subpool);
-          if (!rel_uri || (svn_path_component_count(rel_uri) != 1))
+          const char *rel_path = svn_fspath__is_child(path, child_path, subpool);
+          if (!rel_path || (svn_path_component_count(rel_path) != 1))
             goto loop_it;
         }
 

Modified: subversion/branches/performance/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/dag.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/dag.c Wed Feb  2 13:04:51 2011
@@ -54,6 +54,7 @@
 
 #include "private/svn_skel.h"
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_private_config.h"

Modified: subversion/branches/performance/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/lock.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/lock.c Wed Feb  2 13:04:51 2011
@@ -33,6 +33,7 @@
 #include "err.h"
 #include "bdb/locks-table.h"
 #include "bdb/lock-tokens-table.h"
+#include "util/fs_skels.h"
 #include "../libsvn_fs/fs-loader.h"
 #include "private/svn_fs_util.h"
 
@@ -394,13 +395,41 @@ svn_fs_base__get_lock(svn_lock_t **lock,
   return svn_fs_base__retry_txn(fs, txn_body_get_lock, &args, FALSE, pool);
 }
 
+/* Implements `svn_fs_get_locks_callback_t', spooling lock information
+   to disk as the filesystem provides it.  BATON is an 'apr_file_t *'
+   object pointing to open, writable spool file.  We'll write the
+   spool file with a format like so:
+
+      SKEL1_LEN "\n" SKEL1 "\n" SKEL2_LEN "\n" SKEL2 "\n" ...
+
+   where each skel is a lock skel (the same format we use to store
+   locks in the `locks' table). */
+static svn_error_t *
+spool_locks_info(void *baton,
+                 svn_lock_t *lock,
+                 apr_pool_t *pool)
+{
+  svn_skel_t *lock_skel;
+  apr_file_t *spool_file = (apr_file_t *)baton;
+  const char *skel_len;
+  svn_stringbuf_t *skel_buf;
+
+  SVN_ERR(svn_fs_base__unparse_lock_skel(&lock_skel, lock, pool));
+  skel_buf = svn_skel__unparse(lock_skel, pool);
+  skel_len = apr_psprintf(pool, "%" APR_SIZE_T_FMT "\n", skel_buf->len);
+  SVN_ERR(svn_io_file_write_full(spool_file, skel_len, strlen(skel_len),
+                                 NULL, pool));
+  SVN_ERR(svn_io_file_write_full(spool_file, skel_buf->data,
+                                 skel_buf->len, NULL, pool));
+  return svn_io_file_write_full(spool_file, "\n", 1, NULL, pool);
+}
+
 
 struct locks_get_args
 {
   const char *path;
   svn_depth_t depth;
-  svn_fs_get_locks_callback_t get_locks_func;
-  void *get_locks_baton;
+  apr_file_t *spool_file;
 };
 
 
@@ -409,7 +438,7 @@ txn_body_get_locks(void *baton, trail_t 
 {
   struct locks_get_args *args = baton;
   return svn_fs_bdb__locks_get(trail->fs, args->path, args->depth,
-                               args->get_locks_func, args->get_locks_baton,
+                               spool_locks_info, args->spool_file,
                                trail, trail->pool);
 }
 
@@ -423,13 +452,62 @@ svn_fs_base__get_locks(svn_fs_t *fs,
                        apr_pool_t *pool)
 {
   struct locks_get_args args;
+  apr_off_t offset = 0;
+  svn_stream_t *stream;
+  svn_stringbuf_t *buf;
+  svn_boolean_t eof;
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
+
   args.path = svn_fs__canonicalize_abspath(path, pool);
   args.depth = depth;
-  args.get_locks_func = get_locks_func;
-  args.get_locks_baton = get_locks_baton;
-  return svn_fs_base__retry_txn(fs, txn_body_get_locks, &args, FALSE, pool);
+  SVN_ERR(svn_io_open_uniquely_named(&(args.spool_file), NULL, NULL, NULL,
+                                     NULL, svn_io_file_del_on_close,
+                                     pool, pool));
+  SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_locks, &args, FALSE, pool));
+
+  /* Rewind the spool file, then re-read it, calling GET_LOCKS_FUNC(). */
+  SVN_ERR(svn_io_file_seek(args.spool_file, APR_SET, &offset, pool));
+  stream = svn_stream_from_aprfile2(args.spool_file, FALSE, pool);
+
+  while (1)
+    {
+      apr_size_t len, skel_len;
+      char c, *end, *skel_buf;
+      svn_skel_t *lock_skel;
+      svn_lock_t *lock;
+
+      svn_pool_clear(iterpool);
+
+      /* Read a skel length line and parse it for the skel's length.  */
+      SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof, iterpool));
+      if (eof)
+        break;
+      skel_len = (size_t) strtoul(buf->data, &end, 10);
+      if (skel_len == (size_t) ULONG_MAX || *end != '\0')
+        return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
+
+      /* Now read that much into a buffer. */
+      skel_buf = apr_palloc(pool, skel_len + 1);
+      SVN_ERR(svn_stream_read(stream, skel_buf, &skel_len));
+      skel_buf[skel_len] = '\0';
+
+      /* Read the extra newline that follows the skel. */
+      len = 1;
+      SVN_ERR(svn_stream_read(stream, &c, &len));
+      if (c != '\n')
+        return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
+
+      /* Parse the skel into a lock, and notify the caller. */
+      lock_skel = svn_skel__parse(skel_buf, skel_len, iterpool);
+      SVN_ERR(svn_fs_base__parse_lock_skel(&lock, lock_skel, iterpool));
+      SVN_ERR(get_locks_func(get_locks_baton, lock, iterpool));
+    }
+
+  SVN_ERR(svn_stream_close(stream));
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/branches/performance/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_base/tree.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_base/tree.c Wed Feb  2 13:04:51 2011
@@ -64,6 +64,7 @@
 #include "bdb/node-origins-table.h"
 #include "bdb/miscellaneous-table.h"
 #include "../libsvn_fs/fs-loader.h"
+#include "private/svn_fspath.h"
 #include "private/svn_fs_util.h"
 #include "private/svn_mergeinfo_private.h"
 

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/dag.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/dag.c Wed Feb  2 13:04:51 2011
@@ -36,6 +36,7 @@
 
 #include "../libsvn_fs/fs-loader.h"
 
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 #include "private/svn_temp_serializer.h"
 #include "temp_serializer.h"

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Wed Feb  2 13:04:51 2011
@@ -1969,7 +1969,7 @@ open_pack_or_rev_file(svn_file_handle_ca
         }
 
       if (err && APR_STATUS_IS_ENOENT(err->apr_err)
-      	  && ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
+          && ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
         {
           /* Could not open the file. This may happen if the
            * file once existed but got packed later. Note that

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/lock.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/lock.c Wed Feb  2 13:04:51 2011
@@ -40,6 +40,7 @@
 #include "../libsvn_fs/fs-loader.h"
 
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 /* Names of hash keys used to store a lock for writing to disk. */
@@ -396,7 +397,7 @@ set_lock(const char *fs_path,
                                 digest_path, perms_reference, subpool));
 
       /* Prep for next iteration, or bail if we're done. */
-      if (svn_uri_is_root(this_path->data, this_path->len))
+      if (svn_fspath__is_root(this_path->data, this_path->len))
         break;
       svn_stringbuf_set(this_path,
                         svn_fspath__dirname(this_path->data, subpool));
@@ -464,7 +465,7 @@ delete_lock(svn_fs_t *fs,
         }
 
       /* Prep for next iteration, or bail if we're done. */
-      if (svn_uri_is_root(this_path->data, this_path->len))
+      if (svn_fspath__is_root(this_path->data, this_path->len))
         break;
       svn_stringbuf_set(this_path,
                         svn_fspath__dirname(this_path->data, subpool));

Modified: subversion/branches/performance/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/tree.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/performance/subversion/libsvn_fs_fs/tree.c Wed Feb  2 13:04:51 2011
@@ -61,6 +61,7 @@
 
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 #include "../libsvn_fs/fs-loader.h"
 
 

Modified: subversion/branches/performance/subversion/libsvn_ra/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra/compat.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra/compat.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra/compat.c Wed Feb  2 13:04:51 2011
@@ -33,6 +33,7 @@
 #include "svn_compat.h"
 #include "svn_props.h"
 
+#include "private/svn_fspath.h"
 #include "ra_loader.h"
 #include "svn_private_config.h"
 
@@ -654,8 +655,6 @@ svn_ra__file_revs_from_log(svn_ra_sessio
   svn_node_kind_t kind;
   const char *repos_url;
   const char *session_url;
-  const char *tmp;
-  char *repos_abs_path;
   apr_array_header_t *condensed_targets;
   struct fr_log_message_baton lmb;
   struct rev *rev;
@@ -673,16 +672,11 @@ svn_ra__file_revs_from_log(svn_ra_sessio
   SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, pool));
   SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, pool));
 
-  /* Create the initial path, using the repos_url and session_url */
-  tmp = svn_uri_is_child(repos_url, session_url, pool);
-  repos_abs_path = apr_palloc(pool, strlen(tmp) + 1);
-  repos_abs_path[0] = '/';
-  memcpy(repos_abs_path + 1, tmp, strlen(tmp));
-
   condensed_targets = apr_array_make(pool, 1, sizeof(const char *));
   APR_ARRAY_PUSH(condensed_targets, const char *) = path;
 
-  lmb.path = svn_path_uri_decode(repos_abs_path, pool);
+  lmb.path = svn_fspath__canonicalize(svn_uri_is_child(repos_url, session_url,
+                                                       pool), pool);
   lmb.eldest = NULL;
   lmb.pool = pool;
 

Modified: subversion/branches/performance/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra/ra_loader.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra/ra_loader.c Wed Feb  2 13:04:51 2011
@@ -301,6 +301,16 @@ svn_error_t *svn_ra_open4(svn_ra_session
   /* Initialize the return variable. */
   *session_p = NULL;
 
+  apr_err = apr_uri_parse(sesspool, repos_URL, &repos_URI);
+  /* ### Should apr_uri_parse leave hostname NULL?  It doesn't
+   * for "file:///" URLs, only for bogus URLs like "bogus".
+   * If this is the right behavior for apr_uri_parse, maybe we
+   * should have a svn_uri_parse wrapper. */
+  if (apr_err != APR_SUCCESS || repos_URI.hostname == NULL)
+    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                             _("Illegal repository URL '%s'"),
+                             repos_URL);
+
   if (callbacks->auth_baton)
     {
       /* The 'store-passwords' and 'store-auth-creds' parameters used to
@@ -363,15 +373,6 @@ svn_error_t *svn_ra_open4(svn_ra_session
 
           /* Find out where we're about to connect to, and
            * try to pick a server group based on the destination. */
-          apr_err = apr_uri_parse(sesspool, repos_URL, &repos_URI);
-          /* ### Should apr_uri_parse leave hostname NULL?  It doesn't
-           * for "file:///" URLs, only for bogus URLs like "bogus".
-           * If this is the right behavior for apr_uri_parse, maybe we
-           * should have a svn_uri_parse wrapper. */
-          if (apr_err != APR_SUCCESS || repos_URI.hostname == NULL)
-            return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                     _("Illegal repository URL '%s'"),
-                                     repos_URL);
           server_group = svn_config_find_group(servers, repos_URI.hostname,
                                                SVN_CONFIG_SECTION_GROUPS,
                                                sesspool);
@@ -500,7 +501,19 @@ svn_error_t *svn_ra_open4(svn_ra_session
      what to do. */
   if (corrected_url_p && corrected_url)
     {
-      *corrected_url_p = apr_pstrdup(pool, corrected_url);
+      if (! svn_path_is_url(corrected_url))
+        {
+          /* RFC1945 and RFC2616 state that the Location header's
+             value (from whence this CORRECTED_URL ultimately comes),
+             if present, must be an absolute URI.  But some Apache
+             versions (those older than 2.2.11, it seems) transmit
+             only the path portion of the URI.  See issue #3775 for
+             details. */
+          apr_uri_t corrected_URI = repos_URI;
+          corrected_URI.path = (char *)corrected_url;
+          corrected_url = apr_uri_unparse(pool, &corrected_URI, 0);
+        }
+      *corrected_url_p = svn_uri_canonicalize(corrected_url, pool);
       svn_pool_destroy(sesspool);
       return SVN_NO_ERROR;
     }
@@ -567,7 +580,6 @@ svn_error_t *svn_ra_get_path_relative_to
         return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                                  _("'%s' isn't a child of session URL '%s'"),
                                  url, sess_url);
-      *rel_path = svn_path_uri_decode(*rel_path, pool);
     }
   return SVN_NO_ERROR;
 }
@@ -591,7 +603,6 @@ svn_error_t *svn_ra_get_path_relative_to
                                  _("'%s' isn't a child of repository root "
                                    "URL '%s'"),
                                  url, root_url);
-      *rel_path = svn_path_uri_decode(*rel_path, pool);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/performance/subversion/libsvn_ra/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra/util.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra/util.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra/util.c Wed Feb  2 13:04:51 2011
@@ -38,10 +38,6 @@
 #include "svn_private_config.h"
 #include "private/svn_ra_private.h"
 
-/* Return an error with code SVN_ERR_UNSUPPORTED_FEATURE, and an error
-   message referencing PATH_OR_URL, if the "server" pointed to be
-   RA_SESSION doesn't support Merge Tracking (e.g. is pre-1.5).
-   Perform temporary allocations in POOL. */
 svn_error_t *
 svn_ra__assert_mergeinfo_capable_server(svn_ra_session_t *ra_session,
                                         const char *path_or_url,

Modified: subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_local/ra_plugin.c Wed Feb  2 13:04:51 2011
@@ -36,6 +36,7 @@
 #include "../libsvn_ra/ra_loader.h"
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_repos_private.h"
+#include "private/svn_fspath.h"
 
 #define APR_WANT_STRFUNC
 #include <apr_want.h>
@@ -367,7 +368,7 @@ deltify_etc(const svn_commit_info_t *com
           svn_pool_clear(iterpool);
           apr_hash_this(hi, &rel_path, NULL, &val);
           token = val;
-          abs_path = svn_dirent_join(db->fs_path, rel_path, iterpool);
+          abs_path = svn_fspath__join(db->fs_path, rel_path, iterpool);
           /* We may get errors here if the lock was broken or stolen
              after the commit succeeded.  This is fine and should be
              ignored. */
@@ -508,9 +509,8 @@ svn_ra_local__reparent(svn_ra_session_t 
 
   /* Update our FS_PATH sess member to point to our new
      relative-URL-turned-absolute-filesystem-path. */
-  relpath = apr_pstrcat(pool, "/", svn_path_uri_decode(relpath, pool),
-                        (char *)NULL);
-  svn_stringbuf_set(sess->fs_path, relpath);
+  svn_stringbuf_set(sess->fs_path,
+                    svn_fspath__canonicalize(relpath, pool));
 
   return SVN_NO_ERROR;
 }
@@ -521,9 +521,9 @@ svn_ra_local__get_session_url(svn_ra_ses
                               apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  *url = svn_uri_join(sess->repos_url,
-                      svn_path_uri_encode(sess->fs_path->data + 1, pool),
-                      pool);
+  *url = svn_path_url_add_component2(sess->repos_url,
+                                     sess->fs_path->data + 1,
+                                     pool);
   return SVN_NO_ERROR;
 }
 
@@ -547,7 +547,7 @@ svn_ra_local__get_file_revs(svn_ra_sessi
                             apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
   return svn_repos_get_file_revs2(sess->repos, abs_path, start, end,
                                   include_merged_revisions, NULL, NULL,
                                   handler, handler_baton, pool);
@@ -665,14 +665,14 @@ svn_ra_local__get_commit_editor(svn_ra_s
                hi = apr_hash_next(hi))
             {
               void *val;
-              const char *path, *token;
+              const char *abs_path, *token;
               const void *key;
 
               apr_hash_this(hi, &key, NULL, &val);
-              path = svn_dirent_join(sess->fs_path->data, (const char *)key,
-                                     pool);
+              abs_path = svn_fspath__join(sess->fs_path->data, key, pool);
               token = val;
-              SVN_ERR(svn_fs_access_add_lock_token2(fs_access, path, token));
+              SVN_ERR(svn_fs_access_add_lock_token2(fs_access,
+                                                    abs_path, token));
             }
         }
     }
@@ -710,7 +710,7 @@ svn_ra_local__get_mergeinfo(svn_ra_sessi
     {
       const char *relative_path = APR_ARRAY_IDX(paths, i, const char *);
       APR_ARRAY_PUSH(abs_paths, const char *) =
-        svn_dirent_join(sess->fs_path->data, relative_path, pool);
+        svn_fspath__join(sess->fs_path->data, relative_path, pool);
     }
 
   SVN_ERR(svn_repos_fs_get_mergeinfo2(&tmp_catalog, sess->repos, abs_paths,
@@ -891,7 +891,7 @@ svn_ra_local__get_log(svn_ra_session_t *
         {
           const char *relative_path = APR_ARRAY_IDX(paths, i, const char *);
           APR_ARRAY_PUSH(abs_paths, const char *) =
-            svn_dirent_join(sess->fs_path->data, relative_path, pool);
+            svn_fspath__join(sess->fs_path->data, relative_path, pool);
         }
     }
 
@@ -949,7 +949,7 @@ svn_ra_local__stat(svn_ra_session_t *ses
 {
   svn_ra_local__session_baton_t *sess = session->priv;
   svn_fs_root_t *root;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   if (! SVN_IS_VALID_REVNUM(revision))
     SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
@@ -1017,7 +1017,7 @@ svn_ra_local__get_file(svn_ra_session_t 
   svn_stream_t *contents;
   svn_revnum_t youngest_rev;
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   /* Open the revision's root. */
   if (! SVN_IS_VALID_REVNUM(revision))
@@ -1080,7 +1080,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
   apr_hash_index_t *hi;
   svn_ra_local__session_baton_t *sess = session->priv;
   apr_pool_t *subpool;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   /* Open the revision's root. */
   if (! SVN_IS_VALID_REVNUM(revision))
@@ -1182,7 +1182,7 @@ svn_ra_local__get_locations(svn_ra_sessi
                             apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
   return svn_repos_trace_node_locations(sess->fs, locations, abs_path,
                                         peg_revision, location_revisions,
                                         NULL, NULL, pool);
@@ -1200,7 +1200,7 @@ svn_ra_local__get_location_segments(svn_
                                     apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
   return svn_repos_node_location_segments(sess->repos, abs_path,
                                           peg_revision, start_rev, end_rev,
                                           receiver, receiver_baton,
@@ -1239,7 +1239,7 @@ svn_ra_local__lock(svn_ra_session_t *ses
       path = key;
       revnum = val;
 
-      abs_path = svn_dirent_join(sess->fs_path->data, path, iterpool);
+      abs_path = svn_fspath__join(sess->fs_path->data, path, iterpool);
 
       /* This wrapper will call pre- and post-lock hooks. */
       err = svn_repos_fs_lock(&lock, sess->repos, abs_path, NULL, comment,
@@ -1299,7 +1299,7 @@ svn_ra_local__unlock(svn_ra_session_t *s
       else
         token = NULL;
 
-      abs_path = svn_dirent_join(sess->fs_path->data, path, iterpool);
+      abs_path = svn_fspath__join(sess->fs_path->data, path, iterpool);
 
       /* This wrapper will call pre- and post-unlock hooks. */
       err = svn_repos_fs_unlock(sess->repos, abs_path, token, force,
@@ -1331,7 +1331,7 @@ svn_ra_local__get_lock(svn_ra_session_t 
                        apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
   return svn_fs_get_lock(lock, sess->fs, abs_path, pool);
 }
 
@@ -1345,7 +1345,7 @@ svn_ra_local__get_locks(svn_ra_session_t
                         apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   /* Kinda silly to call the repos wrapper, since we have no authz
      func to give it.  But heck, why not. */
@@ -1432,7 +1432,7 @@ svn_ra_local__get_deleted_rev(svn_ra_ses
                               apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  const char *abs_path = svn_dirent_join(sess->fs_path->data, path, pool);
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
 
   SVN_ERR(svn_repos_deleted_rev(sess->fs,
                                 abs_path,
@@ -1452,15 +1452,15 @@ svn_ra_local__obliterate_path_rev(svn_ra
                                   apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
+  const char *abs_path  = svn_fspath__join(sess->fs_path->data, path, pool);
 
   /* A username is absolutely required to obliterate anything. */
   SVN_ERR(get_username(session, pool));
 
-  path = svn_path_join(sess->fs_path->data, path, pool);
   SVN_ERR(svn_repos__obliterate_path_rev(sess->repos,
                                          sess->username,
                                          revision,
-                                         path,
+                                         abs_path,
                                          pool));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/fetch.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/fetch.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/fetch.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/fetch.c Wed Feb  2 13:04:51 2011
@@ -188,10 +188,11 @@ typedef struct report_baton_t {
   /* Use an intermediate tmpfile for the REPORT response. */
   svn_boolean_t spool_response;
 
-  /* A modern server will understand our "send-all" attribute on the
-     update report request, and will put a "send-all" attribute on
-     its response.  If we see that attribute, we set this to true,
-     otherwise, it stays false (i.e., it's not a modern server). */
+  /* If this report is for a switch, update, or status (but not a
+     merge/diff), then we made the update report request with the "send-all"
+     attribute.  The server reponds to this by putting a "send-all" attribute
+     in its response.  If we see that attribute, we set this to true,
+     otherwise, it stays false. */
   svn_boolean_t receiving_all;
 
   /* Hash mapping 'const char *' paths -> 'const char *' lock tokens. */
@@ -944,7 +945,7 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
           svn_dirent_t *entry;
 
           apr_hash_this(hi, &key, NULL, &val);
-          childname =  key;
+          childname = svn_relpath_canonicalize(key, pool);
           resource = val;
 
           /* Skip the effective '.' entry that comes back from
@@ -1051,7 +1052,8 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
             }
 
           apr_hash_set(*dirents,
-                       svn_path_uri_decode(svn_uri_basename(childname, pool),
+                       svn_path_uri_decode(svn_relpath_basename(childname,
+                                                                pool),
                                            pool),
                        APR_HASH_KEY_STRING, entry);
         }
@@ -1588,19 +1590,16 @@ start_element(int *elem, void *userdata,
       /* push the new baton onto the directory baton stack */
       push_dir(rb, new_dir_baton, pathbuf, subpool);
 
-      /* Property fetching is implied in addition.  This flag is only
-         for parsing old-style reports; it is ignored when talking to
-         a modern server. */
+      /* Property fetching is implied in addition. */
       TOP_DIR(rb).fetch_props = TRUE;
 
       bc_url = svn_xml_get_attr_value("bc-url", atts);
 
-      /* In non-modern report responses, we're just told to fetch the
+      /* If we are not in send-all mode, we're just told to fetch the
          props later.  In that case, we can at least do a pre-emptive
          depth-1 propfind on the directory right now; this prevents
          individual propfinds on added-files later on, thus reducing
-         the number of network turnarounds (though not by as much as
-         simply getting a modern report response!).  */
+         the number of network turnarounds. */
       if ((! rb->receiving_all) && bc_url)
         {
           apr_hash_t *bc_children;
@@ -1711,9 +1710,7 @@ start_element(int *elem, void *userdata,
                                       crev, rb->file_pool,
                                       &rb->file_baton));
 
-      /* Property fetching is implied in addition.  This flag is only
-         for parsing old-style reports; it is ignored when talking to
-         a modern server. */
+      /* Property fetching is implied in addition. */
       rb->fetch_props = TRUE;
 
       break;

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/get_locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/get_locks.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/get_locks.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/get_locks.c Wed Feb  2 13:04:51 2011
@@ -44,6 +44,7 @@
 #include "svn_time.h"
 
 #include "private/svn_dav_protocol.h"
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 #include "ra_neon.h"
@@ -121,7 +122,7 @@ static const svn_ra_neon__xml_elm_t getl
 
 /* Context for parsing server's response. */
 typedef struct get_locks_baton_t {
-  const char *path;                /* target of the report */
+  const char *path;                /* fspath target of the report */
   svn_depth_t requested_depth;     /* requested depth of the report */
   svn_lock_t *current_lock;        /* the lock being constructed */
   svn_stringbuf_t *cdata_accum;    /* a place to accumulate cdata */
@@ -256,9 +257,9 @@ getlocks_end_element(void *userdata, int
       else if ((baton->requested_depth == svn_depth_files) ||
                (baton->requested_depth == svn_depth_immediates))
         {
-          const char *rel_uri = svn_uri_is_child(baton->path,
-                                                 baton->current_lock->path,
-                                                 baton->scratchpool);
+          const char *rel_uri = svn_fspath__is_child(baton->path,
+                                                     baton->current_lock->path,
+                                                     baton->scratchpool);
           if (rel_uri && (svn_path_component_count(rel_uri) == 1))
             apr_hash_set(baton->lock_hash, baton->current_lock->path,
                          APR_HASH_KEY_STRING, baton->current_lock);
@@ -268,9 +269,12 @@ getlocks_end_element(void *userdata, int
 
     case ELEM_lock_path:
       /* neon has already xml-unescaped the cdata for us. */
-      baton->current_lock->path = apr_pstrmemdup(baton->pool,
-                                                 baton->cdata_accum->data,
-                                                 baton->cdata_accum->len);
+      baton->current_lock->path =
+        svn_fspath__canonicalize(apr_pstrmemdup(baton->scratchpool,
+                                                baton->cdata_accum->data,
+                                                baton->cdata_accum->len),
+                                 baton->pool);
+
       /* clean up the accumulator. */
       svn_stringbuf_setempty(baton->cdata_accum);
       svn_pool_clear(baton->scratchpool);
@@ -379,7 +383,7 @@ svn_ra_neon__get_locks(svn_ra_session_t 
                                                  url, pool));
 
   baton.lock_hash = apr_hash_make(pool);
-  baton.path = apr_pstrcat(pool, "/", rel_path, (char *)NULL);
+  baton.path = svn_fspath__canonicalize(rel_path, pool);
   baton.requested_depth = depth;
   baton.pool = pool;
   baton.scratchpool = svn_pool_create(pool);

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/options.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/options.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/options.c Wed Feb  2 13:04:51 2011
@@ -29,6 +29,8 @@
 #include "svn_private_config.h"
 #include "../libsvn_ra/ra_loader.h"
 
+#include "private/svn_fspath.h"
+
 #include "ra_neon.h"
 
 
@@ -108,9 +110,9 @@ end_element(void *baton, int state,
   options_ctx_t *oc = baton;
 
   if (state == ELEM_href)
-    oc->activity_coll = svn_string_create(svn_uri_canonicalize(oc->cdata->data,
-                                                               oc->pool),
-                                          oc->pool);
+    oc->activity_coll =
+      svn_string_create(svn_urlpath__canonicalize(oc->cdata->data, oc->pool),
+                        oc->pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/props.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/props.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/props.c Wed Feb  2 13:04:51 2011
@@ -41,6 +41,7 @@
 #include "../libsvn_ra/ra_loader.h"
 
 #include "private/svn_dav_protocol.h"
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 #include "ra_neon.h"
@@ -413,7 +414,8 @@ static svn_error_t * end_element(void *b
     case ELEM_href:
       /* Special handling for <href> that belongs to the <response> tag. */
       if (rsrc->href_parent == ELEM_response)
-        return assign_rsrc_url(pc->rsrc, svn_uri_canonicalize(cdata, pc->pool),
+        return assign_rsrc_url(pc->rsrc,
+                               svn_urlpath__canonicalize(cdata, pc->pool),
                                pc->pool);
 
       /* Use the parent element's name, not the href. */
@@ -425,7 +427,7 @@ static svn_error_t * end_element(void *b
 
       /* All other href's we'll treat as property values. */
       name = parent_defn->name;
-      value = svn_string_create(svn_uri_canonicalize(cdata, pc->pool),
+      value = svn_string_create(svn_urlpath__canonicalize(cdata, pc->pool),
                                 pc->pool);
       break;
 
@@ -723,8 +725,10 @@ svn_ra_neon__search_for_starting_props(s
         return err;  /* found a _real_ error */
 
       /* else... lop off the basename and try again. */
+      /* ### TODO: path_s is an absolute, schema-less URI, but
+         ### technically not an FS_PATH. */
       svn_stringbuf_set(lopped_path,
-                        svn_path_join(svn_uri_basename(path_s->data, iterpool),
+                        svn_path_join(svn_path_basename(path_s->data, iterpool),
                                       lopped_path->data, iterpool));
 
       len = path_s->len;

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/ra_neon.h Wed Feb  2 13:04:51 2011
@@ -1010,6 +1010,16 @@ const char *
 svn_ra_neon__request_get_location(svn_ra_neon__request_t *request,
                                   apr_pool_t *pool);
 
+/* Canonicalize an absolute URI, in the general sense.  URI might be a
+ * full, absolute, schema-ful URL.  It might be just the path portion
+ * of a URL.  Whatever the case, it is a URI-encoded identifier of
+ * *some sort*, as will be the returned form thereof.
+ */
+const char *
+svn_ra_neon__uri_canonicalize(const char *uri,
+                              apr_pool_t *scratch_pool,
+                              apr_pool_t *result_pool);
+
 
 /*
  * Implements the get_locations RA layer function. */

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/session.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/session.c Wed Feb  2 13:04:51 2011
@@ -1155,7 +1155,6 @@ svn_ra_neon__get_path_relative_to_root(s
                                  _("'%s' isn't a child of repository root "
                                    "URL '%s'"),
                                  url, root_url);
-      *rel_path = svn_path_uri_decode(*rel_path, pool);
     }
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/performance/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_neon/util.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_neon/util.c Wed Feb  2 13:04:51 2011
@@ -39,6 +39,7 @@
 #include "svn_xml.h"
 #include "svn_props.h"
 
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 #include "ra_neon.h"
@@ -1570,8 +1571,5 @@ svn_ra_neon__request_get_location(svn_ra
                                   apr_pool_t *pool)
 {
   const char *val = ne_get_response_header(request->ne_req, "Location");
-  return val ? svn_uri_join(request->url,
-                            svn_uri_canonicalize(val, pool),
-                            pool)
-             : NULL;
+  return val ? svn_urlpath__canonicalize(val, pool) : NULL;
 }

Modified: subversion/branches/performance/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/commit.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/commit.c Wed Feb  2 13:04:51 2011
@@ -41,6 +41,7 @@
 
 #include "svn_private_config.h"
 #include "private/svn_dep_compat.h"
+#include "private/svn_fspath.h"
 
 #include "ra_serf.h"
 #include "../libsvn_ra/ra_loader.h"
@@ -311,7 +312,7 @@ handle_checkout(serf_request_t *request,
       if (status)
         err = svn_error_compose_create(svn_error_wrap_apr(status, NULL), err);
 
-      ctx->resource_url = svn_uri_canonicalize(uri.path, ctx->pool);
+      ctx->resource_url = svn_urlpath__canonicalize(uri.path, ctx->pool);
     }
 
   return err;
@@ -487,7 +488,8 @@ get_version_url(const char **checked_in_
 
       if (current_version)
         {
-          *checked_in_url = svn_uri_canonicalize(current_version->data, pool);
+          *checked_in_url =
+            svn_urlpath__canonicalize(current_version->data, pool);
           return SVN_NO_ERROR;
         }
     }
@@ -542,7 +544,7 @@ get_version_url(const char **checked_in_
                                  _("Path '%s' not present"),
                                  session->repos_url.path);
 
-      root_checkout = svn_uri_canonicalize(root_checkout, pool);
+      root_checkout = svn_urlpath__canonicalize(root_checkout, pool);
     }
 
   *checked_in_url = svn_path_url_add_component2(root_checkout, relpath, pool);
@@ -1114,7 +1116,7 @@ setup_copy_dir_headers(serf_bucket_t *he
     {
       uri.path = (char *)svn_path_url_add_component2(
         dir->parent_dir->checkout->resource_url,
-        svn_uri_basename(dir->name, pool),
+        svn_relpath_basename(dir->name, pool),
         pool);
     }
   absolute_uri = apr_uri_unparse(pool, &uri, 0);
@@ -1504,7 +1506,8 @@ delete_entry(const char *path,
       /* Ensure our directory has been checked out */
       SVN_ERR(checkout_dir(dir));
       delete_target = svn_path_url_add_component2(dir->checkout->resource_url,
-                                                  svn_uri_basename(path, pool),
+                                                  svn_relpath_basename(path,
+                                                                       pool),
                                                   pool);
     }
 
@@ -1619,7 +1622,7 @@ add_directory(const char *path,
                                              path, dir->pool);
       mkcol_target = svn_path_url_add_component2(
                                parent->checkout->resource_url,
-                               svn_uri_basename(path, dir->pool),
+                               svn_relpath_basename(path, dir->pool),
                                dir->pool);
     }
 
@@ -1870,7 +1873,7 @@ add_file(const char *path,
 
       new_file->url =
         svn_path_url_add_component2(dir->checkout->resource_url,
-                                    svn_uri_basename(path, new_file->pool),
+                                    svn_relpath_basename(path, new_file->pool),
                                     new_file->pool);
     }
 

Modified: subversion/branches/performance/subversion/libsvn_ra_serf/getlocks.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/getlocks.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/getlocks.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/getlocks.c Wed Feb  2 13:04:51 2011
@@ -41,6 +41,7 @@
 #include "svn_time.h"
 
 #include "private/svn_dav_protocol.h"
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 #include "ra_serf.h"
@@ -203,10 +204,10 @@ end_getlocks(svn_ra_serf__xml_parser_t *
       else if ((lock_ctx->requested_depth == svn_depth_files) ||
                (lock_ctx->requested_depth == svn_depth_immediates))
         {
-          const char *rel_uri = svn_uri_is_child(lock_ctx->path,
-                                                 info->lock->path,
-                                                 info->pool);
-          if (rel_uri && (svn_path_component_count(rel_uri) == 1))
+          const char *rel_path = svn_fspath__is_child(lock_ctx->path,
+                                                      info->lock->path,
+                                                      info->pool);
+          if (rel_path && (svn_path_component_count(rel_path) == 1))
             apr_hash_set(lock_ctx->hash, info->lock->path,
                          APR_HASH_KEY_STRING, info->lock);
         }

Modified: subversion/branches/performance/subversion/libsvn_ra_serf/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_ra_serf/merge.c?rev=1066452&r1=1066451&r2=1066452&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_ra_serf/merge.c (original)
+++ subversion/branches/performance/subversion/libsvn_ra_serf/merge.c Wed Feb  2 13:04:51 2011
@@ -40,6 +40,7 @@
 #include "svn_props.h"
 
 #include "private/svn_dav_protocol.h"
+#include "private/svn_fspath.h"
 #include "svn_private_config.h"
 
 #include "ra_serf.h"
@@ -297,7 +298,7 @@ end_merge(svn_ra_serf__xml_parser_t *par
           const char *href;
 
           href = apr_hash_get(info->props, "href", APR_HASH_KEY_STRING);
-          if (! svn_uri_is_ancestor(ctx->merge_url, href))
+          if (! svn_urlpath__is_ancestor(ctx->merge_url, href))
             {
               /* ### need something better than APR_EGENERAL */
               return svn_error_createf(APR_EGENERAL, NULL,
@@ -319,7 +320,7 @@ end_merge(svn_ra_serf__xml_parser_t *par
                  an ancestor of HREF.  All that remains is to
                  determine of HREF is the same as CTX->MERGE_URL, or --
                  if not -- is relative value as a child thereof. */
-              href = svn_uri_is_child(ctx->merge_url, href, NULL);
+              href = svn_urlpath__is_child(ctx->merge_url, href, NULL);
               if (! href)
                 href = "";
 
@@ -364,7 +365,8 @@ end_merge(svn_ra_serf__xml_parser_t *par
       info->prop_val = apr_pstrmemdup(info->pool, info->prop_val,
                                       info->prop_val_len);
       if (strcmp(info->prop_name, "href") == 0)
-        info->prop_val = svn_uri_canonicalize(info->prop_val, info->pool);
+        info->prop_val = svn_urlpath__canonicalize(info->prop_val,
+                                                       info->pool);
 
       /* Set our property. */
       apr_hash_set(info->props, info->prop_name, APR_HASH_KEY_STRING,
@@ -452,7 +454,7 @@ svn_ra_serf__merge_lock_token_list(apr_h
       path.data = key;
       path.len = klen;
 
-      if (parent && !svn_uri_is_ancestor(parent, key))
+      if (parent && !svn_relpath_is_ancestor(parent, key))
         continue;
 
       svn_ra_serf__add_open_tag_buckets(body, alloc, "S:lock", NULL);



Mime
View raw message