subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1685464 [9/43] - in /subversion/branches/fsx-1.10: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/svncopy/ doc/ notes/ subversion/bindings/javahl/ subversion/bindings/javahl/native/ subversion/bi...
Date Sun, 14 Jun 2015 20:58:16 GMT
Modified: subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c Sun Jun 14 20:58:10 2015
@@ -36,6 +36,20 @@
 #include "private/svn_string_private.h"
 #include "private/svn_dep_compat.h"
 
+static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 };
+static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 };
+
+#define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0))
+
+static const char *
+get_svndiff_header(int version)
+{
+  if (version == 1)
+    return SVNDIFF_V1;
+  else
+    return SVNDIFF_V0;
+}
+
 /* ----- Text delta to svndiff ----- */
 
 /* We make one of these and get it passed back to us in calls to the
@@ -46,7 +60,8 @@ struct encoder_baton {
   svn_boolean_t header_done;
   int version;
   int compression_level;
-  apr_pool_t *pool;
+  /* Pool for temporary allocations, will be cleared periodically. */
+  apr_pool_t *scratch_pool;
 };
 
 /* This is at least as big as the largest size for a single instruction. */
@@ -72,7 +87,7 @@ static svn_error_t *
 send_simple_insertion_window(svn_txdelta_window_t *window,
                              struct encoder_baton *eb)
 {
-  unsigned char headers[4 + 5 * SVN__MAX_ENCODED_UINT_LEN
+  unsigned char headers[SVNDIFF_HEADER_SIZE + 5 * SVN__MAX_ENCODED_UINT_LEN
                           + MAX_INSTRUCTION_LEN];
   unsigned char ibuf[MAX_INSTRUCTION_LEN];
   unsigned char *header_current;
@@ -89,11 +104,8 @@ send_simple_insertion_window(svn_txdelta
   if (!eb->header_done)
     {
       eb->header_done = TRUE;
-      headers[0] = 'S';
-      headers[1] = 'V';
-      headers[2] = 'N';
-      headers[3] = (unsigned char)eb->version;
-      header_current = headers + 4;
+      memcpy(headers, get_svndiff_header(eb->version), SVNDIFF_HEADER_SIZE);
+      header_current = headers + SVNDIFF_HEADER_SIZE;
     }
   else
     {
@@ -135,58 +147,28 @@ send_simple_insertion_window(svn_txdelta
   return SVN_NO_ERROR;
 }
 
+/* Encodes delta window WINDOW to svndiff-format.
+   The svndiff version is VERSION. COMPRESSION_LEVEL is the zlib
+   compression level to use.
+   Returned values will be allocated in POOL or refer to *WINDOW
+   fields. */
 static svn_error_t *
-window_handler(svn_txdelta_window_t *window, void *baton)
+encode_window(svn_stringbuf_t **instructions_p,
+              svn_stringbuf_t **header_p,
+              const svn_string_t **newdata_p,
+              svn_txdelta_window_t *window,
+              int version,
+              int compression_level,
+              apr_pool_t *pool)
 {
-  struct encoder_baton *eb = baton;
-  apr_pool_t *pool;
   svn_stringbuf_t *instructions;
-  svn_stringbuf_t *i1;
   svn_stringbuf_t *header;
   const svn_string_t *newdata;
   unsigned char ibuf[MAX_INSTRUCTION_LEN], *ip;
   const svn_txdelta_op_t *op;
-  apr_size_t len;
-
-  /* use specialized code if there is no source */
-  if (window && !window->src_ops && window->num_ops == 1 && !eb->version)
-    return svn_error_trace(send_simple_insertion_window(window, eb));
-
-  /* Make sure we write the header.  */
-  if (!eb->header_done)
-    {
-      char svnver[4] = {'S','V','N','\0'};
-      len = 4;
-      svnver[3] = (char)eb->version;
-      SVN_ERR(svn_stream_write(eb->output, svnver, &len));
-      eb->header_done = TRUE;
-    }
-
-  if (window == NULL)
-    {
-      svn_stream_t *output = eb->output;
-
-      /* We're done; clean up.
-
-         We clean our pool first. Given that the output stream was passed
-         TO us, we'll assume it has a longer lifetime, and that it will not
-         be affected by our pool destruction.
-
-         The contrary point of view (close the stream first): that could
-         tell our user that everything related to the output stream is done,
-         and a cleanup of the user pool should occur. However, that user
-         pool could include the subpool we created for our work (eb->pool),
-         which would then make our call to svn_pool_destroy() puke.
-       */
-      svn_pool_destroy(eb->pool);
-
-      return svn_stream_close(output);
-    }
 
   /* create the necessary data buffers */
-  pool = svn_pool_create(eb->pool);
   instructions = svn_stringbuf_create_empty(pool);
-  i1 = svn_stringbuf_create_empty(pool);
   header = svn_stringbuf_create_empty(pool);
 
   /* Encode the instructions.  */
@@ -213,21 +195,21 @@ window_handler(svn_txdelta_window_t *win
   append_encoded_int(header, window->sview_offset);
   append_encoded_int(header, window->sview_len);
   append_encoded_int(header, window->tview_len);
-  if (eb->version == 1)
+  if (version == 1)
     {
-      SVN_ERR(svn__compress(instructions, i1, eb->compression_level));
-      instructions = i1;
+      svn_stringbuf_t *compressed_instructions;
+      compressed_instructions = svn_stringbuf_create_empty(pool);
+      SVN_ERR(svn__compress(instructions->data, instructions->len,
+                            compressed_instructions, compression_level));
+      instructions = compressed_instructions;
     }
   append_encoded_int(header, instructions->len);
-  if (eb->version == 1)
+  if (version == 1)
     {
       svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool);
-      svn_stringbuf_t *original = svn_stringbuf_create_empty(pool);
-      original->data = (char *)window->new_data->data; /* won't be modified */
-      original->len = window->new_data->len;
-      original->blocksize = window->new_data->len + 1;
 
-      SVN_ERR(svn__compress(original, compressed, eb->compression_level));
+      SVN_ERR(svn__compress(window->new_data->data, window->new_data->len,
+                            compressed, compression_level));
       newdata = svn_stringbuf__morph_into_string(compressed);
     }
   else
@@ -235,6 +217,51 @@ window_handler(svn_txdelta_window_t *win
 
   append_encoded_int(header, newdata->len);
 
+  *instructions_p = instructions;
+  *header_p = header;
+  *newdata_p = newdata;
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+window_handler(svn_txdelta_window_t *window, void *baton)
+{
+  struct encoder_baton *eb = baton;
+  apr_size_t len;
+  svn_stringbuf_t *instructions;
+  svn_stringbuf_t *header;
+  const svn_string_t *newdata;
+
+  /* use specialized code if there is no source */
+  if (window && !window->src_ops && window->num_ops == 1 && !eb->version)
+    return svn_error_trace(send_simple_insertion_window(window, eb));
+
+  /* Make sure we write the header.  */
+  if (!eb->header_done)
+    {
+      len = SVNDIFF_HEADER_SIZE;
+      SVN_ERR(svn_stream_write(eb->output, get_svndiff_header(eb->version),
+                               &len));
+      eb->header_done = TRUE;
+    }
+
+  if (window == NULL)
+    {
+      /* We're done; clean up. */
+      SVN_ERR(svn_stream_close(eb->output));
+
+      svn_pool_destroy(eb->scratch_pool);
+
+      return SVN_NO_ERROR;
+    }
+
+  svn_pool_clear(eb->scratch_pool);
+
+  SVN_ERR(encode_window(&instructions, &header, &newdata, window,
+                        eb->version, eb->compression_level,
+                        eb->scratch_pool));
+
   /* Write out the window.  */
   len = header->len;
   SVN_ERR(svn_stream_write(eb->output, header->data, &len));
@@ -249,7 +276,6 @@ window_handler(svn_txdelta_window_t *win
       SVN_ERR(svn_stream_write(eb->output, newdata->data, &len));
     }
 
-  svn_pool_destroy(pool);
   return SVN_NO_ERROR;
 }
 
@@ -261,13 +287,12 @@ svn_txdelta_to_svndiff3(svn_txdelta_wind
                         int compression_level,
                         apr_pool_t *pool)
 {
-  apr_pool_t *subpool = svn_pool_create(pool);
   struct encoder_baton *eb;
 
-  eb = apr_palloc(subpool, sizeof(*eb));
+  eb = apr_palloc(pool, sizeof(*eb));
   eb->output = output;
   eb->header_done = FALSE;
-  eb->pool = subpool;
+  eb->scratch_pool = svn_pool_create(pool);
   eb->version = svndiff_version;
   eb->compression_level = compression_level;
 
@@ -334,6 +359,17 @@ struct decode_baton
 
   /* svndiff version in use by delta.  */
   unsigned char version;
+
+  /* Length of parsed delta window header. 0 if window is not parsed yet. */
+  apr_size_t window_header_len;
+
+  /* Five integer fields of parsed delta window header. Valid only if
+     WINDOW_HEADER_LEN > 0 */
+  svn_filesize_t  sview_offset;
+  apr_size_t sview_len;
+  apr_size_t tview_len;
+  apr_size_t inslen;
+  apr_size_t newlen;
 };
 
 
@@ -360,7 +396,7 @@ decode_size(apr_size_t *val,
   const unsigned char *result = svn__decode_uint(&temp, p, end);
   if (temp > APR_SIZE_MAX)
     return NULL;
-  
+
   *val = (apr_size_t)temp;
   return result;
 }
@@ -483,21 +519,6 @@ count_and_verify_instructions(int *ninst
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out,
-            apr_size_t limit)
-{
-  /* construct a fake string buffer as parameter to svn__decompress.
-     This is fine as that function never writes to it. */
-  svn_stringbuf_t compressed;
-  compressed.pool = NULL;
-  compressed.data = (char *)in;
-  compressed.len = inLen;
-  compressed.blocksize = inLen + 1;
-  
-  return svn__decompress(&compressed, out, limit);
-}
-
 /* Given the five integer fields of a window header and a pointer to
    the remainder of the window contents, fill in a delta window
    structure *WINDOW.  New allocations will be performed in POOL;
@@ -513,7 +534,7 @@ decode_window(svn_txdelta_window_t *wind
   int ninst;
   apr_size_t npos;
   svn_txdelta_op_t *ops, *op;
-  svn_string_t *new_data = apr_palloc(pool, sizeof(*new_data));
+  svn_string_t *new_data;
 
   window->sview_offset = sview_offset;
   window->sview_len = sview_len;
@@ -526,28 +547,22 @@ decode_window(svn_txdelta_window_t *wind
       svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool);
       svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool);
 
-      SVN_ERR(zlib_decode(insend, newlen, ndout,
-                          SVN_DELTA_WINDOW_SIZE));
-      SVN_ERR(zlib_decode(data, insend - data, instout,
-                          MAX_INSTRUCTION_SECTION_LEN));
+      SVN_ERR(svn__decompress(insend, newlen, ndout,
+                              SVN_DELTA_WINDOW_SIZE));
+      SVN_ERR(svn__decompress(data, insend - data, instout,
+                              MAX_INSTRUCTION_SECTION_LEN));
 
       newlen = ndout->len;
       data = (unsigned char *)instout->data;
       insend = (unsigned char *)instout->data + instout->len;
 
-      new_data->data = (const char *) ndout->data;
-      new_data->len = newlen;
+      new_data = svn_stringbuf__morph_into_string(ndout);
     }
   else
     {
       /* Copy the data because an svn_string_t must have the invariant
          data[len]=='\0'. */
-      char *buf = apr_palloc(pool, newlen + 1);
-
-      memcpy(buf, insend, newlen);
-      buf[newlen] = '\0';
-      new_data->data = buf;
-      new_data->len = newlen;
+      new_data = svn_string_ncreate((const char*)insend, newlen, pool);
     }
 
   /* Count the instructions and make sure they are all valid.  */
@@ -578,10 +593,6 @@ decode_window(svn_txdelta_window_t *wind
   return SVN_NO_ERROR;
 }
 
-static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 };
-static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 };
-#define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0))
-
 static svn_error_t *
 write_handler(void *baton,
               const char *buffer,
@@ -589,8 +600,6 @@ write_handler(void *baton,
 {
   struct decode_baton *db = (struct decode_baton *) baton;
   const unsigned char *p, *end;
-  svn_filesize_t sview_offset;
-  apr_size_t sview_len, tview_len, inslen, newlen, remaining;
   apr_size_t buflen = *len;
 
   /* Chew up four bytes at the beginning for the header.  */
@@ -628,90 +637,114 @@ write_handler(void *baton,
 
   while (1)
     {
-      apr_pool_t *newpool;
       svn_txdelta_window_t window;
 
       /* Read the header, if we have enough bytes for that.  */
       p = (const unsigned char *) db->buffer->data;
       end = (const unsigned char *) db->buffer->data + db->buffer->len;
 
-      p = decode_file_offset(&sview_offset, p, end);
-      if (p == NULL)
-        return SVN_NO_ERROR;
-
-      p = decode_size(&sview_len, p, end);
-      if (p == NULL)
-        return SVN_NO_ERROR;
-
-      p = decode_size(&tview_len, p, end);
-      if (p == NULL)
-        return SVN_NO_ERROR;
-
-      p = decode_size(&inslen, p, end);
-      if (p == NULL)
-        return SVN_NO_ERROR;
-
-      p = decode_size(&newlen, p, end);
-      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 + SVN__MAX_ENCODED_UINT_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
-          || (apr_size_t)sview_offset + sview_len < (apr_size_t)sview_offset)
-        return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,
-                                _("Svndiff contains corrupt window header"));
-
-      /* Check for source windows which slide backwards.  */
-      if (sview_len > 0
-          && (sview_offset < db->last_sview_offset
+      if (db->window_header_len == 0)
+        {
+          svn_filesize_t sview_offset;
+          apr_size_t sview_len, tview_len, inslen, newlen;
+          const unsigned char *hdr_start = p;
+
+          p = decode_file_offset(&sview_offset, p, end);
+          if (p == NULL)
+              break;
+
+          p = decode_size(&sview_len, p, end);
+          if (p == NULL)
+              break;
+
+          p = decode_size(&tview_len, p, end);
+          if (p == NULL)
+              break;
+
+          p = decode_size(&inslen, p, end);
+          if (p == NULL)
+              break;
+
+          p = decode_size(&newlen, p, end);
+          if (p == NULL)
+              break;
+
+          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 + SVN__MAX_ENCODED_UINT_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
+              || (apr_size_t)sview_offset + sview_len < (apr_size_t)sview_offset)
+            return svn_error_create(
+                      SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,
+                      _("Svndiff contains corrupt window header"));
+
+          /* Check for source windows which slide backwards.  */
+          if (sview_len > 0
+              && (sview_offset < db->last_sview_offset
               || (sview_offset + sview_len
                   < db->last_sview_offset + db->last_sview_len)))
-        return svn_error_create
-          (SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL,
-           _("Svndiff has backwards-sliding source views"));
+            return svn_error_create(
+                     SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL,
+                     _("Svndiff has backwards-sliding source views"));
+
+          /* Remember parsed window header. */
+          db->window_header_len = p - hdr_start;
+          db->sview_offset = sview_offset;
+          db->sview_len = sview_len;
+          db->tview_len = tview_len;
+          db->inslen = inslen;
+          db->newlen = newlen;
+        }
+      else
+        {
+          /* Skip already parsed window header. */
+          p += db->window_header_len;
+        }
 
       /* Wait for more data if we don't have enough bytes for the
          whole window.  */
-      if ((apr_size_t) (end - p) < inslen + newlen)
+      if ((apr_size_t) (end - p) < db->inslen + db->newlen)
         return SVN_NO_ERROR;
 
       /* Decode the window and send it off. */
-      SVN_ERR(decode_window(&window, sview_offset, sview_len, tview_len,
-                            inslen, newlen, p, db->subpool,
-                            db->version));
+      SVN_ERR(decode_window(&window, db->sview_offset, db->sview_len,
+                            db->tview_len, db->inslen, db->newlen, p,
+                            db->subpool, db->version));
       SVN_ERR(db->consumer_func(&window, db->consumer_baton));
 
-      /* Make a new subpool and buffer, saving aside the remaining
-         data in the old buffer.  */
-      newpool = svn_pool_create(db->pool);
-      p += inslen + newlen;
-      remaining = db->buffer->data + db->buffer->len - (const char *) p;
-      db->buffer =
-        svn_stringbuf_ncreate((const char *) p, remaining, newpool);
+      p += db->inslen + db->newlen;
+
+      /* Remove processed data from the buffer.  */
+      svn_stringbuf_remove(db->buffer, 0, db->buffer->len - (end - p));
+
+      /* Reset window header length. */
+      db->window_header_len = 0;
 
       /* Remember the offset and length of the source view for next time.  */
-      db->last_sview_offset = sview_offset;
-      db->last_sview_len = sview_len;
+      db->last_sview_offset = db->sview_offset;
+      db->last_sview_len = db->sview_len;
 
-      /* We've copied stuff out of the old pool. Toss that pool and use
-         our new pool.
-         ### might be nice to avoid the copy and just use svn_pool_clear
-         ### to get rid of whatever the "other stuff" is. future project...
-      */
-      svn_pool_destroy(db->subpool);
-      db->subpool = newpool;
+      /* Clear subpool. */
+      svn_pool_clear(db->subpool);
     }
 
-  /* NOTREACHED */
+  /* At this point we processed all integral windows and DB->BUFFER is empty
+     or contains partially read window header.
+     Check that unprocessed data is not larger than theoretical maximum
+     window header size. */
+  if (db->buffer->len > 5 * SVN__MAX_ENCODED_UINT_LEN)
+    return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,
+                            _("Svndiff contains a too-large window header"));
+
+  return SVN_NO_ERROR;
 }
 
 /* Minimal svn_stream_t write handler, doing nothing */
@@ -749,23 +782,25 @@ svn_txdelta_parse_svndiff(svn_txdelta_wi
                           svn_boolean_t error_on_early_close,
                           apr_pool_t *pool)
 {
-  apr_pool_t *subpool = svn_pool_create(pool);
-  struct decode_baton *db = apr_palloc(pool, sizeof(*db));
   svn_stream_t *stream;
 
-  db->consumer_func = handler;
-  db->consumer_baton = handler_baton;
-  db->pool = subpool;
-  db->subpool = svn_pool_create(subpool);
-  db->buffer = svn_stringbuf_create_empty(db->subpool);
-  db->last_sview_offset = 0;
-  db->last_sview_len = 0;
-  db->header_bytes = 0;
-  db->error_on_early_close = error_on_early_close;
-  stream = svn_stream_create(db, pool);
-
   if (handler != svn_delta_noop_window_handler)
     {
+      apr_pool_t *subpool = svn_pool_create(pool);
+      struct decode_baton *db = apr_palloc(pool, sizeof(*db));
+
+      db->consumer_func = handler;
+      db->consumer_baton = handler_baton;
+      db->pool = subpool;
+      db->subpool = svn_pool_create(subpool);
+      db->buffer = svn_stringbuf_create_empty(db->pool);
+      db->last_sview_offset = 0;
+      db->last_sview_len = 0;
+      db->header_bytes = 0;
+      db->error_on_early_close = error_on_early_close;
+      db->window_header_len = 0;
+      stream = svn_stream_create(db, pool);
+
       svn_stream_set_write(stream, write_handler);
       svn_stream_set_close(stream, close_handler);
     }
@@ -773,6 +808,7 @@ svn_txdelta_parse_svndiff(svn_txdelta_wi
     {
       /* And else we just ignore everything as efficiently as we can.
          by only hooking a no-op handler */
+      stream = svn_stream_create(NULL, pool);
       svn_stream_set_write(stream, noop_write_handler);
     }
   return stream;
@@ -796,7 +832,7 @@ read_one_byte(unsigned char *byte, svn_s
   return SVN_NO_ERROR;
 }
 
-/* Read and decode one integer from STREAM into *SIZE. 
+/* Read and decode one integer from STREAM into *SIZE.
    Increment *BYTE_COUNTER by the number of chars we have read. */
 static svn_error_t *
 read_one_size(apr_size_t *size,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c Sun Jun 14 20:58:10 2015
@@ -180,8 +180,7 @@ svn_txdelta_window_dup(const svn_txdelta
   build_baton.num_ops = window->num_ops;
   build_baton.src_ops = window->src_ops;
   build_baton.ops_size = window->num_ops;
-  build_baton.ops = apr_palloc(pool, ops_size);
-  memcpy(build_baton.ops, window->ops, ops_size);
+  build_baton.ops = apr_pmemdup(pool, window->ops, ops_size);
   build_baton.new_data =
     svn_stringbuf_create_from_string(window->new_data, pool);
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c Sun Jun 14 20:58:10 2015
@@ -42,7 +42,6 @@ create_compressed(apr_file_t **result,
 {
   svn_stream_t *compressed;
   svn_filesize_t bytes_read = 0;
-  apr_finfo_t finfo;
   apr_size_t rd;
 
   SVN_ERR(svn_io_open_uniquely_named(result, NULL, NULL, "diffgz",
@@ -56,7 +55,7 @@ create_compressed(apr_file_t **result,
   if (original_stream)
     do
     {
-      char buffer[SVN_STREAM_CHUNK_SIZE];
+      char buffer[SVN__STREAM_CHUNK_SIZE];
       rd = sizeof(buffer);
 
       if (cancel_func)
@@ -67,7 +66,7 @@ create_compressed(apr_file_t **result,
       bytes_read += rd;
       SVN_ERR(svn_stream_write(compressed, buffer, &rd));
     }
-    while(rd == SVN_STREAM_CHUNK_SIZE);
+    while(rd == SVN__STREAM_CHUNK_SIZE);
   else
     {
       apr_size_t zero = 0;
@@ -77,8 +76,7 @@ create_compressed(apr_file_t **result,
   SVN_ERR(svn_stream_close(compressed)); /* Flush compression */
 
   *full_size = bytes_read;
-  SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, *result, scratch_pool));
-  *compressed_size = finfo.size;
+  SVN_ERR(svn_io_file_size_get(compressed_size, *result, scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c Sun Jun 14 20:58:10 2015
@@ -777,7 +777,6 @@ datasources_open(void *baton,
 {
   svn_diff__file_baton_t *file_baton = baton;
   struct file_info files[4];
-  apr_finfo_t finfo[4];
   apr_off_t length[4];
 #ifndef SVN_DISABLE_PREFIX_SUFFIX_SCANNING
   svn_boolean_t reached_one_eof;
@@ -792,14 +791,14 @@ datasources_open(void *baton,
   /* Open datasources and read first chunk */
   for (i = 0; i < datasources_len; i++)
     {
+      svn_filesize_t filesize;
       struct file_info *file
           = &file_baton->files[datasource_to_index(datasources[i])];
       SVN_ERR(svn_io_file_open(&file->file, file->path,
                                APR_READ, APR_OS_DEFAULT, file_baton->pool));
-      SVN_ERR(svn_io_file_info_get(&finfo[i], APR_FINFO_SIZE,
-                                   file->file, file_baton->pool));
-      file->size = finfo[i].size;
-      length[i] = finfo[i].size > CHUNK_SIZE ? CHUNK_SIZE : finfo[i].size;
+      SVN_ERR(svn_io_file_size_get(&filesize, file->file, file_baton->pool));
+      file->size = filesize;
+      length[i] = filesize > CHUNK_SIZE ? CHUNK_SIZE : filesize;
       file->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]);
       SVN_ERR(read_chunk(file->file, file->buffer,
                          length[i], 0, file_baton->pool));
@@ -1956,7 +1955,7 @@ typedef struct context_saver_t {
   const char **data; /* const char *data[context_size] */
   apr_size_t *len;   /* apr_size_t len[context_size] */
   apr_size_t next_slot;
-  apr_size_t total_written;
+  apr_ssize_t total_writes;
 } context_saver_t;
 
 
@@ -1972,7 +1971,7 @@ context_saver_stream_write(void *baton,
       cs->data[cs->next_slot] = data;
       cs->len[cs->next_slot] = *len;
       cs->next_slot = (cs->next_slot + 1) % cs->context_size;
-      cs->total_written++;
+      cs->total_writes++;
     }
   return SVN_NO_ERROR;
 }
@@ -2252,7 +2251,7 @@ output_conflict_with_context(svn_diff3__
      trailing context)?  If so, flush it. */
   if (btn->output_stream == btn->context_saver->stream)
     {
-      if (btn->context_saver->total_written > btn->context_size)
+      if (btn->context_saver->total_writes > btn->context_size)
         SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
       SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
     }
@@ -2360,7 +2359,7 @@ svn_diff_file_output_merge3(svn_stream_t
                             svn_diff_conflict_display_style_t style,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
-                            apr_pool_t *pool)
+                            apr_pool_t *scratch_pool)
 {
   svn_diff3__file_output_baton_t baton;
   apr_file_t *file[3];
@@ -2376,7 +2375,7 @@ svn_diff_file_output_merge3(svn_stream_t
   baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
   if (conflicts_only)
     {
-      baton.pool = svn_pool_create(pool);
+      baton.pool = svn_pool_create(scratch_pool);
       make_context_saver(&baton);
       baton.real_output_stream = output_stream;
     }
@@ -2387,22 +2386,22 @@ svn_diff_file_output_merge3(svn_stream_t
   baton.path[2] = latest_path;
   SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_modified,
                                     conflict_modified ? conflict_modified
-                                    : apr_psprintf(pool, "<<<<<<< %s",
+                                    : apr_psprintf(scratch_pool, "<<<<<<< %s",
                                                    modified_path),
-                                    pool));
+                                    scratch_pool));
   SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_original,
                                     conflict_original ? conflict_original
-                                    : apr_psprintf(pool, "||||||| %s",
+                                    : apr_psprintf(scratch_pool, "||||||| %s",
                                                    original_path),
-                                    pool));
+                                    scratch_pool));
   SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_separator,
                                     conflict_separator ? conflict_separator
-                                    : "=======", pool));
+                                    : "=======", scratch_pool));
   SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_latest,
                                     conflict_latest ? conflict_latest
-                                    : apr_psprintf(pool, ">>>>>>> %s",
+                                    : apr_psprintf(scratch_pool, ">>>>>>> %s",
                                                    latest_path),
-                                    pool));
+                                    scratch_pool));
 
   baton.conflict_style = style;
 
@@ -2413,7 +2412,7 @@ svn_diff_file_output_merge3(svn_stream_t
       SVN_ERR(map_or_read_file(&file[idx],
                                MMAP_T_ARG(mm[idx])
                                &baton.buffer[idx], &size,
-                               baton.path[idx], pool));
+                               baton.path[idx], scratch_pool));
 
       baton.curp[idx] = baton.buffer[idx];
       baton.endp[idx] = baton.buffer[idx];
@@ -2454,7 +2453,7 @@ svn_diff_file_output_merge3(svn_stream_t
 
       if (file[idx])
         {
-          SVN_ERR(svn_io_file_close(file[idx], pool));
+          SVN_ERR(svn_io_file_close(file[idx], scratch_pool));
         }
     }
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c Sun Jun 14 20:58:10 2015
@@ -622,7 +622,7 @@ svn_diff_mem_string_output_unified3(svn_
                                     int context_size,
                                     svn_cancel_func_t cancel_func,
                                     void *cancel_baton,
-                                    apr_pool_t *pool)
+                                    apr_pool_t *scratch_pool)
 {
 
   if (svn_diff_contains_diffs(diff))
@@ -631,9 +631,9 @@ svn_diff_mem_string_output_unified3(svn_
 
       memset(&baton, 0, sizeof(baton));
       baton.output_stream = output_stream;
-      baton.pool = svn_pool_create(pool);
+      baton.pool = svn_pool_create(scratch_pool);
       baton.header_encoding = header_encoding;
-      baton.hunk = svn_stringbuf_create_empty(pool);
+      baton.hunk = svn_stringbuf_create_empty(scratch_pool);
       baton.hunk_delimiter = hunk_delimiter;
       baton.no_newline_string
         = (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
@@ -644,22 +644,22 @@ svn_diff_mem_string_output_unified3(svn_
 
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_context]), " ",
-               header_encoding, pool));
+               header_encoding, scratch_pool));
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_delete]), "-",
-               header_encoding, pool));
+               header_encoding, scratch_pool));
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_insert]), "+",
-               header_encoding, pool));
+               header_encoding, scratch_pool));
 
-      fill_source_tokens(&baton.sources[0], original, pool);
-      fill_source_tokens(&baton.sources[1], modified, pool);
+      fill_source_tokens(&baton.sources[0], original, scratch_pool);
+      fill_source_tokens(&baton.sources[1], modified, scratch_pool);
 
       if (with_diff_header)
         {
           SVN_ERR(svn_diff__unidiff_write_header(
                     output_stream, header_encoding,
-                    original_header, modified_header, pool));
+                    original_header, modified_header, scratch_pool));
         }
 
       SVN_ERR(svn_diff_output2(diff, &baton,
@@ -688,7 +688,7 @@ typedef struct context_saver_t {
   const char **data; /* const char *data[context_size] */
   apr_size_t *len;   /* apr_size_t len[context_size] */
   apr_size_t next_slot;
-  apr_size_t total_written;
+  apr_ssize_t total_writes;
 } context_saver_t;
 
 
@@ -701,7 +701,7 @@ context_saver_stream_write(void *baton,
   cs->data[cs->next_slot] = data;
   cs->len[cs->next_slot] = *len;
   cs->next_slot = (cs->next_slot + 1) % cs->context_size;
-  cs->total_written++;
+  cs->total_writes++;
   return SVN_NO_ERROR;
 }
 
@@ -822,13 +822,11 @@ make_trailing_context_printer(merge_outp
 
 
 static svn_error_t *
-output_merge_token_range(apr_size_t *lines_printed_p,
-                         merge_output_baton_t *btn,
+output_merge_token_range(merge_output_baton_t *btn,
                          int idx, apr_off_t first,
                          apr_off_t length)
 {
   apr_array_header_t *tokens = btn->sources[idx].tokens;
-  apr_size_t lines_printed = 0;
 
   for (; length > 0 && first < tokens->nelts; length--, first++)
     {
@@ -838,12 +836,8 @@ output_merge_token_range(apr_size_t *lin
       /* Note that the trailing context printer assumes that
          svn_stream_write is called exactly once per line. */
       SVN_ERR(svn_stream_write(btn->output_stream, token->data, &len));
-      lines_printed++;
     }
 
-  if (lines_printed_p)
-    *lines_printed_p = lines_printed;
-
   return SVN_NO_ERROR;
 }
 
@@ -866,7 +860,7 @@ output_common_modified(void *baton,
                        apr_off_t modified_start, apr_off_t modified_length,
                        apr_off_t latest_start, apr_off_t latest_length)
 {
-  return output_merge_token_range(NULL, baton, 1/*modified*/,
+  return output_merge_token_range(baton, 1/*modified*/,
                                   modified_start, modified_length);
 }
 
@@ -876,7 +870,7 @@ output_latest(void *baton,
               apr_off_t modified_start, apr_off_t modified_length,
               apr_off_t latest_start, apr_off_t latest_length)
 {
-  return output_merge_token_range(NULL, baton, 2/*latest*/,
+  return output_merge_token_range(baton, 2/*latest*/,
                                   latest_start, latest_length);
 }
 
@@ -920,26 +914,26 @@ output_conflict(void *baton,
       style == svn_diff_conflict_display_modified_original_latest)
     {
       SVN_ERR(output_merge_marker(btn, 1/*modified*/));
-      SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
+      SVN_ERR(output_merge_token_range(btn, 1/*modified*/,
                                        modified_start, modified_length));
 
       if (style == svn_diff_conflict_display_modified_original_latest)
         {
           SVN_ERR(output_merge_marker(btn, 0/*original*/));
-          SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/,
+          SVN_ERR(output_merge_token_range(btn, 0/*original*/,
                                            original_start, original_length));
         }
 
       SVN_ERR(output_merge_marker(btn, 2/*separator*/));
-      SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
+      SVN_ERR(output_merge_token_range(btn, 2/*latest*/,
                                        latest_start, latest_length));
       SVN_ERR(output_merge_marker(btn, 3/*latest (end)*/));
     }
   else if (style == svn_diff_conflict_display_modified)
-      SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
+      SVN_ERR(output_merge_token_range(btn, 1/*modified*/,
                                        modified_start, modified_length));
   else if (style == svn_diff_conflict_display_latest)
-      SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
+      SVN_ERR(output_merge_token_range(btn, 2/*latest*/,
                                        latest_start, latest_length));
   else /* unknown style */
     SVN_ERR_MALFUNCTION();
@@ -983,7 +977,7 @@ output_conflict_with_context(void *baton
      trailing context)?  If so, flush it. */
   if (btn->output_stream == btn->context_saver->stream)
     {
-      if (btn->context_saver->total_written > btn->context_size)
+      if (btn->context_saver->total_writes > btn->context_size)
         SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
       SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
     }
@@ -995,17 +989,17 @@ output_conflict_with_context(void *baton
   SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[1],
                                               modified_start,
                                               modified_length));
-  SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
+  SVN_ERR(output_merge_token_range(btn, 1/*modified*/,
                                    modified_start, modified_length));
 
   SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[0],
                                               original_start,
                                               original_length));
-  SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/,
+  SVN_ERR(output_merge_token_range(btn, 0/*original*/,
                                    original_start, original_length));
 
   SVN_ERR(output_merge_marker(btn, 2/*separator*/));
-  SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
+  SVN_ERR(output_merge_token_range(btn, 2/*latest*/,
                                    latest_start, latest_length));
   SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[3],
                                               latest_start,
@@ -1066,7 +1060,7 @@ svn_diff_mem_string_output_merge3(svn_st
                                   svn_diff_conflict_display_style_t style,
                                   svn_cancel_func_t cancel_func,
                                   void *cancel_baton,
-                                  apr_pool_t *pool)
+                                  apr_pool_t *scratch_pool)
 {
   merge_output_baton_t btn;
   const char *eol;
@@ -1080,16 +1074,16 @@ svn_diff_mem_string_output_merge3(svn_st
 
   if (conflicts_only)
     {
-      btn.pool = svn_pool_create(pool);
+      btn.pool = svn_pool_create(scratch_pool);
       make_context_saver(&btn);
       btn.real_output_stream = output_stream;
     }
   else
     btn.output_stream = output_stream;
 
-  fill_source_tokens(&(btn.sources[0]), original, pool);
-  fill_source_tokens(&(btn.sources[1]), modified, pool);
-  fill_source_tokens(&(btn.sources[2]), latest, pool);
+  fill_source_tokens(&(btn.sources[0]), original, scratch_pool);
+  fill_source_tokens(&(btn.sources[1]), modified, scratch_pool);
+  fill_source_tokens(&(btn.sources[2]), latest, scratch_pool);
 
   btn.conflict_style = style;
 
@@ -1110,22 +1104,22 @@ svn_diff_mem_string_output_merge3(svn_st
                                     conflict_modified
                                     ? conflict_modified
                                     : "<<<<<<< (modified)",
-                                    pool));
+                                    scratch_pool));
   SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[0],
                                     conflict_original
                                     ? conflict_original
                                     : "||||||| (original)",
-                                    pool));
+                                    scratch_pool));
   SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[2],
                                     conflict_separator
                                     ? conflict_separator
                                     : "=======",
-                                    pool));
+                                    scratch_pool));
   SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[3],
                                     conflict_latest
                                     ? conflict_latest
                                     : ">>>>>>> (latest)",
-                                    pool));
+                                    scratch_pool));
 
   SVN_ERR(svn_diff_output2(diff, &btn, vtable, cancel_func, cancel_baton));
   if (conflicts_only)

Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c Sun Jun 14 20:58:10 2015
@@ -532,7 +532,7 @@ parse_mergeinfo(svn_boolean_t *found_mer
         }
       else
         SVN_ERR(err);
-                            
+
       if (mergeinfo)
         {
           if (hunk->original_length > 0) /* reverse merges */

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c Sun Jun 14 20:58:10 2015
@@ -249,7 +249,7 @@ can_modify(svn_fs_root_t *txn_root,
       svn_fs_close_root(rev_root);
 
       /* Has the target node changed in the future?  */
-      if (relation != svn_fs_node_same)
+      if (relation != svn_fs_node_unchanged)
         {
           /* Restarting the commit will base the txn on the future/new
              revision, allowing the modification at REVISION.  */
@@ -777,16 +777,24 @@ svn_fs__editor_commit(svn_revnum_t *revi
   /* Clean up internal resources (eg. eb->root). This also allows the
      editor infrastructure to know this editor is "complete".  */
   err = svn_editor_complete(editor);
+  if (err)
+    {
+      svn_fs_txn_t *txn = eb->txn;
+
+      eb->txn = NULL;
+      return svn_error_trace(svn_error_compose_create(
+                  err,
+                  svn_fs_abort_txn(txn, scratch_pool)));
+    }
 
   /* Note: docco for svn_fs_commit_txn() states that CONFLICT_PATH will
      be allocated in the txn's pool. But it lies. Regardless, we want
      it placed into RESULT_POOL.  */
 
-  if (!err)
-    err = svn_fs_commit_txn(&inner_conflict_path,
-                             revision,
-                             eb->txn,
-                             scratch_pool);
+  err = svn_fs_commit_txn(&inner_conflict_path,
+                          revision,
+                          eb->txn,
+                          scratch_pool);
   if (SVN_IS_VALID_REVNUM(*revision))
     {
       if (err)

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c Sun Jun 14 20:58:10 2015
@@ -27,7 +27,6 @@
 #include <apr_atomic.h>
 #include <apr_hash.h>
 #include <apr_md5.h>
-#include <apr_thread_mutex.h>
 #include <apr_uuid.h>
 #include <apr_strings.h>
 
@@ -140,7 +139,7 @@ load_module(fs_init_func_t *initfunc, co
                                  _("Invalid name for FS type '%s'"),
                                  name);
 
-    libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.%d",
+    libname = apr_psprintf(pool, "libsvn_fs_%s-" SVN_DSO_SUFFIX_FMT,
                            name, SVN_VER_MAJOR, SVN_SOVERSION);
     funcname = apr_psprintf(pool, "svn_fs_%s__init", name);
 
@@ -408,6 +407,11 @@ synchronized_initialize(void *baton, apr
 svn_error_t *
 svn_fs_initialize(apr_pool_t *pool)
 {
+#if defined(SVN_USE_DSO) && APR_HAS_DSO
+  /* Ensure that DSO subsystem is initialized early as possible if
+     we're going to use it. */
+  SVN_ERR(svn_dso_initialize2());
+#endif
   /* Protect against multiple calls. */
   return svn_error_trace(svn_atomic__init_once(&common_pool_initialized,
                                                synchronized_initialize,
@@ -436,6 +440,8 @@ default_warning_func(void *baton, svn_er
 svn_error_t *
 svn_fs__path_valid(const char *path, apr_pool_t *pool)
 {
+  char *c;
+
   /* UTF-8 encoded string without NULs. */
   if (! svn_utf__cstring_is_valid(path))
     {
@@ -452,6 +458,18 @@ svn_fs__path_valid(const char *path, apr
                                path);
     }
 
+  /* Raise an error if PATH contains a newline because svn:mergeinfo and
+     friends can't handle them.  Issue #4340 describes a similar problem
+     in the FSFS code itself.
+   */
+  c = strchr(path, '\n');
+  if (c)
+    {
+      return svn_error_createf(SVN_ERR_FS_PATH_SYNTAX, NULL,
+               _("Invalid control character '0x%02x' in path '%s'"),
+               (unsigned char)*c, svn_path_illegal_path_escape(path, pool));
+    }
+
   /* That's good enough. */
   return SVN_NO_ERROR;
 }
@@ -542,19 +560,19 @@ svn_fs_upgrade2(const char *path,
                 void *notify_baton,
                 svn_cancel_func_t cancel_func,
                 void *cancel_baton,
-                apr_pool_t *pool)
+                apr_pool_t *scratch_pool)
 {
   fs_library_vtable_t *vtable;
   svn_fs_t *fs;
 
-  SVN_ERR(fs_library_vtable(&vtable, path, pool));
-  fs = fs_new(NULL, pool);
+  SVN_ERR(fs_library_vtable(&vtable, path, scratch_pool));
+  fs = fs_new(NULL, scratch_pool);
 
   SVN_ERR(vtable->upgrade_fs(fs, path,
                              notify_func, notify_baton,
                              cancel_func, cancel_baton,
                              common_pool_lock,
-                             pool, common_pool));
+                             scratch_pool, common_pool));
   return SVN_NO_ERROR;
 }
 
@@ -897,26 +915,48 @@ svn_fs_list_transactions(apr_array_heade
   return svn_error_trace(fs->vtable->list_transactions(names_p, fs, pool));
 }
 
+static svn_boolean_t
+is_internal_txn_prop(const char *name)
+{
+  return strcmp(name, SVN_FS__PROP_TXN_CHECK_LOCKS) == 0 ||
+         strcmp(name, SVN_FS__PROP_TXN_CHECK_OOD) == 0 ||
+         strcmp(name, SVN_FS__PROP_TXN_CLIENT_DATE) == 0;
+}
+
 svn_error_t *
 svn_fs_txn_prop(svn_string_t **value_p, svn_fs_txn_t *txn,
                 const char *propname, apr_pool_t *pool)
 {
+  if (is_internal_txn_prop(propname))
+    {
+      *value_p = NULL;
+      return SVN_NO_ERROR;
+    }
+
   return svn_error_trace(txn->vtable->get_prop(value_p, txn, propname, pool));
 }
 
 svn_error_t *
 svn_fs_txn_proplist(apr_hash_t **table_p, svn_fs_txn_t *txn, apr_pool_t *pool)
 {
-  return svn_error_trace(txn->vtable->get_proplist(table_p, txn, pool));
+  SVN_ERR(txn->vtable->get_proplist(table_p, txn, pool));
+
+  /* Don't give away internal transaction properties. */
+  svn_hash_sets(*table_p, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL);
+  svn_hash_sets(*table_p, SVN_FS__PROP_TXN_CHECK_OOD, NULL);
+  svn_hash_sets(*table_p, SVN_FS__PROP_TXN_CLIENT_DATE, NULL);
+
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_change_txn_prop(svn_fs_txn_t *txn, const char *name,
                        const svn_string_t *value, apr_pool_t *pool)
 {
-  /* Silently drop attempts to modify the internal property. */
-  if (!strcmp(name, SVN_FS__PROP_TXN_CLIENT_DATE))
-    return SVN_NO_ERROR;
+  if (is_internal_txn_prop(name))
+    return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                             _("Attempt to modify internal transaction "
+                               "property '%s'"), name);
 
   return svn_error_trace(txn->vtable->change_prop(txn, name, value, pool));
 }
@@ -927,25 +967,14 @@ svn_fs_change_txn_props(svn_fs_txn_t *tx
 {
   int i;
 
-  /* Silently drop attempts to modify the internal property. */
   for (i = 0; i < props->nelts; ++i)
     {
       svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
 
-      if (!strcmp(prop->name, SVN_FS__PROP_TXN_CLIENT_DATE))
-        {
-          apr_array_header_t *reduced_props
-            = apr_array_make(pool, props->nelts - 1, sizeof(svn_prop_t));
-
-          for (i = 0; i < props->nelts; ++i)
-            {
-              prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
-              if (strcmp(prop->name, SVN_FS__PROP_TXN_CLIENT_DATE))
-                APR_ARRAY_PUSH(reduced_props, svn_prop_t) = *prop;
-            }
-          props = reduced_props;
-          break;
-        }
+      if (is_internal_txn_prop(prop->name))
+        return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                 _("Attempt to modify internal transaction "
+                                   "property '%s'"), prop->name);
     }
 
   return svn_error_trace(txn->vtable->change_props(txn, props, pool));
@@ -1111,7 +1140,7 @@ svn_error_t *
 svn_fs_node_relation(svn_fs_node_relation_t *relation,
                      svn_fs_root_t *root_a, const char *path_a,
                      svn_fs_root_t *root_b, const char *path_b,
-                     apr_pool_t *pool)
+                     apr_pool_t *scratch_pool)
 {
   /* Different repository types? */
   if (root_a->fs != root_b->fs)
@@ -1120,9 +1149,10 @@ svn_fs_node_relation(svn_fs_node_relatio
       return SVN_NO_ERROR;
     }
 
-  return svn_error_trace(root_a->vtable->node_relation(relation, root_a,
-                                                       path_a, root_b,
-                                                       path_b, pool));
+  return svn_error_trace(root_a->vtable->node_relation(relation,
+                                                       root_a, path_a,
+                                                       root_b, path_b,
+                                                       scratch_pool));
 }
 
 svn_error_t *
@@ -1166,6 +1196,16 @@ svn_fs_node_proplist(apr_hash_t **table_
 }
 
 svn_error_t *
+svn_fs_node_has_props(svn_boolean_t *has_props,
+                      svn_fs_root_t *root,
+                      const char *path,
+                      apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(root->vtable->node_has_props(has_props, root, path,
+                                                      scratch_pool));
+}
+
+svn_error_t *
 svn_fs_change_node_prop(svn_fs_root_t *root, const char *path,
                         const char *name, const svn_string_t *value,
                         apr_pool_t *pool)
@@ -1177,12 +1217,12 @@ svn_fs_change_node_prop(svn_fs_root_t *r
 svn_error_t *
 svn_fs_props_different(svn_boolean_t *changed_p, svn_fs_root_t *root1,
                        const char *path1, svn_fs_root_t *root2,
-                       const char *path2, apr_pool_t *pool)
+                       const char *path2, apr_pool_t *scratch_pool)
 {
   return svn_error_trace(root1->vtable->props_changed(changed_p,
                                                       root1, path1,
                                                       root2, path2,
-                                                      TRUE, pool));
+                                                      TRUE, scratch_pool));
 }
 
 svn_error_t *
@@ -1290,10 +1330,13 @@ svn_error_t *
 svn_fs_dir_optimal_order(apr_array_header_t **ordered_p,
                          svn_fs_root_t *root,
                          apr_hash_t *entries,
-                         apr_pool_t *pool)
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
 {
   return svn_error_trace(root->vtable->dir_optimal_order(ordered_p, root,
-                                                         entries, pool));
+                                                         entries,
+                                                         result_pool,
+                                                         scratch_pool));
 }
 
 svn_error_t *
@@ -1454,12 +1497,13 @@ svn_fs_apply_text(svn_stream_t **content
 svn_error_t *
 svn_fs_contents_different(svn_boolean_t *changed_p, svn_fs_root_t *root1,
                           const char *path1, svn_fs_root_t *root2,
-                          const char *path2, apr_pool_t *pool)
+                          const char *path2, apr_pool_t *scratch_pool)
 {
   return svn_error_trace(root1->vtable->contents_changed(changed_p,
                                                          root1, path1,
                                                          root2, path2,
-                                                         TRUE, pool));
+                                                         TRUE,
+                                                         scratch_pool));
 }
 
 svn_error_t *
@@ -1617,20 +1661,24 @@ svn_fs_lock_many(svn_fs_t *fs,
                                     target->token, "opaquelocktoken");
 
           if (!err)
-            for (c = target->token; *c && !err; c++)
-              if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c))
+            {
+              for (c = target->token; *c && !err; c++)
+                if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c))
+                  err = svn_error_createf(
+                          SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+                          _("Lock token '%s' is not ASCII or is a "
+                            "control character at byte %u"),
+                          target->token,
+                          (unsigned)(c - target->token));
+
+              /* strlen(token) == c - token. */
+              if (!err && !svn_xml_is_xml_safe(target->token,
+                                               c - target->token))
                 err = svn_error_createf(
-                        SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
-                        _("Lock token '%s' is not ASCII or is a "
-                          "control character at byte %u"),
-                        target->token,
-                        (unsigned)(c - target->token));
-
-          /* strlen(token) == c - token. */
-          if (!err && !svn_xml_is_xml_safe(target->token, c - target->token))
-            err = svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
-                                    _("Lock token URI '%s' is not XML-safe"),
-                                    target->token);
+                            SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+                            _("Lock token URI '%s' is not XML-safe"),
+                            target->token);
+            }
         }
 
       if (err)
@@ -1691,7 +1739,7 @@ svn_fs_lock(svn_lock_t **lock, svn_fs_t
             apr_pool_t *pool)
 {
   apr_hash_t *targets = apr_hash_make(pool);
-  svn_fs_lock_target_t target; 
+  svn_fs_lock_target_t target;
   svn_error_t *err;
   struct lock_baton_t baton = {0};
 
@@ -1710,7 +1758,7 @@ svn_fs_lock(svn_lock_t **lock, svn_fs_t
     svn_error_compose(err, baton.fs_err);
   else if (!err)
     err = baton.fs_err;
-  
+
   return svn_error_trace(err);
 }
 
@@ -1723,9 +1771,10 @@ svn_fs_generate_lock_token(const char **
 svn_fs_lock_target_t *
 svn_fs_lock_target_create(const char *token,
                           svn_revnum_t current_rev,
-                          apr_pool_t *pool)
+                          apr_pool_t *result_pool)
 {
-  svn_fs_lock_target_t *target = apr_palloc(pool, sizeof(svn_fs_lock_target_t));
+  svn_fs_lock_target_t *target = apr_palloc(result_pool,
+                                            sizeof(svn_fs_lock_target_t));
 
   target->token = token;
   target->current_rev = current_rev;
@@ -1863,7 +1912,7 @@ svn_fs_compare_ids(const svn_fs_id_t *a,
 {
   switch (a->vtable->compare(a, b))
     {
-    case svn_fs_node_same:
+    case svn_fs_node_unchanged:
       return 0;
     case svn_fs_node_common_ancestor:
       return 1;
@@ -1958,7 +2007,7 @@ svn_fs_info_dup(const void *info_void,
   fs_library_vtable_t *vtable;
 
   SVN_ERR(get_library_vtable(&vtable, info->fs_type, scratch_pool));
-  
+
   if (vtable->info_fsap_dup)
     return vtable->info_fsap_dup(info_void, result_pool);
   else

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h Sun Jun 14 20:58:10 2015
@@ -99,7 +99,7 @@ typedef struct fs_library_vtable_t
                              svn_cancel_func_t cancel_func,
                              void *cancel_baton,
                              svn_mutex__t *common_pool_lock,
-                             apr_pool_t *pool,
+                             apr_pool_t *scratch_pool,
                              apr_pool_t *common_pool);
   svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
                             svn_revnum_t start,
@@ -314,7 +314,7 @@ typedef struct root_vtable_t
   svn_error_t *(*node_relation)(svn_fs_node_relation_t *relation,
                                 svn_fs_root_t *root_a, const char *path_a,
                                 svn_fs_root_t *root_b, const char *path_b,
-                                apr_pool_t *pool);
+                                apr_pool_t *scratch_pool);
   svn_error_t *(*node_created_rev)(svn_revnum_t *revision,
                                    svn_fs_root_t *root, const char *path,
                                    apr_pool_t *pool);
@@ -346,6 +346,8 @@ typedef struct root_vtable_t
                             apr_pool_t *pool);
   svn_error_t *(*node_proplist)(apr_hash_t **table_p, svn_fs_root_t *root,
                                 const char *path, apr_pool_t *pool);
+  svn_error_t *(*node_has_props)(svn_boolean_t *has_props, svn_fs_root_t *root,
+                                 const char *path, apr_pool_t *scratch_pool);
   svn_error_t *(*change_node_prop)(svn_fs_root_t *root, const char *path,
                                    const char *name,
                                    const svn_string_t *value,
@@ -353,7 +355,7 @@ typedef struct root_vtable_t
   svn_error_t *(*props_changed)(int *changed_p, svn_fs_root_t *root1,
                                 const char *path1, svn_fs_root_t *root2,
                                 const char *path2, svn_boolean_t strict,
-                                apr_pool_t *pool);
+                                apr_pool_t *scratch_pool);
 
   /* Directories */
   svn_error_t *(*dir_entries)(apr_hash_t **entries_p, svn_fs_root_t *root,
@@ -361,7 +363,8 @@ typedef struct root_vtable_t
   svn_error_t *(*dir_optimal_order)(apr_array_header_t **ordered_p,
                                     svn_fs_root_t *root,
                                     apr_hash_t *entries,
-                                    apr_pool_t *pool);
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool);
   svn_error_t *(*make_dir)(svn_fs_root_t *root, const char *path,
                            apr_pool_t *pool);
 
@@ -394,7 +397,7 @@ typedef struct root_vtable_t
   svn_error_t *(*contents_changed)(int *changed_p, svn_fs_root_t *root1,
                                    const char *path1, svn_fs_root_t *root2,
                                    const char *path2, svn_boolean_t strict,
-                                   apr_pool_t *pool);
+                                   apr_pool_t *scratch_pool);
   svn_error_t *(*get_file_delta_stream)(svn_txdelta_stream_t **stream_p,
                                         svn_fs_root_t *source_root,
                                         const char *source_path,
@@ -446,7 +449,7 @@ typedef struct id_vtable_t
 /*** Definitions of the abstract FS object types ***/
 
 /* These are transaction properties that correspond to the bitfields
-   in the 'flags' argument to svn_fs_lock().  */
+   in the 'flags' argument to svn_fs_begin_txn2().  */
 #define SVN_FS__PROP_TXN_CHECK_LOCKS           SVN_PROP_PREFIX "check-locks"
 #define SVN_FS__PROP_TXN_CHECK_OOD             SVN_PROP_PREFIX "check-ood"
 /* Set to "0" at the start of the txn, to "1" when svn:date changes. */

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c Sun Jun 14 20:58:10 2015
@@ -79,6 +79,9 @@ svn_fs_bdb__get_rev(revision_t **revisio
      numbers begin with one.  */
   db_recno_t recno = (db_recno_t) rev + 1;
 
+  if (!SVN_IS_VALID_REVNUM(rev))
+    return svn_fs_base__err_dangling_rev(fs, rev);
+
   svn_fs_base__trail_debug(trail, "revisions", "get");
   db_err = bfd->revisions->get(bfd->revisions, trail->db_txn,
                                svn_fs_base__set_dbt(&key, &recno,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c Sun Jun 14 20:58:10 2015
@@ -780,7 +780,7 @@ base_create(svn_fs_t *fs,
   ((base_fs_data_t *) fs->fsap_data)->format = format;
 
   SVN_ERR(populate_opened_fs(fs, pool));
-  return SVN_NO_ERROR;;
+  return SVN_NO_ERROR;
 
 error:
   return svn_error_compose_create(svn_err,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c Sun Jun 14 20:58:10 2015
@@ -113,7 +113,7 @@ svn_fs_base__id_compare(const svn_fs_id_
                         const svn_fs_id_t *b)
 {
   if (svn_fs_base__id_eq(a, b))
-    return svn_fs_node_same;
+    return svn_fs_node_unchanged;
   return (svn_fs_base__id_check_related(a, b) ? svn_fs_node_common_ancestor
                                               : svn_fs_node_unrelated);
 }

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c Sun Jun 14 20:58:10 2015
@@ -39,6 +39,7 @@
 #include "private/svn_fs_util.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_dep_compat.h"
+#include "revs-txns.h"
 
 
 /* Add LOCK and its associated LOCK_TOKEN (associated with PATH) as
@@ -241,8 +242,11 @@ svn_fs_base__lock(svn_fs_t *fs,
 {
   apr_hash_index_t *hi;
   svn_error_t *cb_err = SVN_NO_ERROR;
+  svn_revnum_t youngest_rev = SVN_INVALID_REVNUM;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
+  SVN_ERR(svn_fs_base__youngest_rev(&youngest_rev, fs, scratch_pool));
 
   for (hi = apr_hash_first(scratch_pool, targets); hi; hi = apr_hash_next(hi))
     {
@@ -250,8 +254,9 @@ svn_fs_base__lock(svn_fs_t *fs,
       const char *path = apr_hash_this_key(hi);
       const svn_fs_lock_target_t *target = apr_hash_this_val(hi);
       svn_lock_t *lock;
-      svn_error_t *err;
+      svn_error_t *err = NULL;
 
+      svn_pool_clear(iterpool);
       args.lock_p = &lock;
       args.path = svn_fs__canonicalize_abspath(path, result_pool);
       args.token = target->token;
@@ -261,13 +266,23 @@ svn_fs_base__lock(svn_fs_t *fs,
       args.expiration_date = expiration_date;
       args.current_rev = target->current_rev;
       args.result_pool = result_pool;
-      
-      err = svn_fs_base__retry_txn(fs, txn_body_lock, &args, TRUE,
-                                   scratch_pool);
+
+      if (SVN_IS_VALID_REVNUM(target->current_rev))
+        {
+          if (target->current_rev > youngest_rev)
+            err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+                                    _("No such revision %ld"),
+                                    target->current_rev);
+        }
+
+      if (!err)
+        err = svn_fs_base__retry_txn(fs, txn_body_lock, &args, TRUE,
+                                     iterpool);
       if (!cb_err && lock_callback)
-        cb_err = lock_callback(lock_baton, args.path, lock, err, scratch_pool);
+        cb_err = lock_callback(lock_baton, args.path, lock, err, iterpool);
       svn_error_clear(err);
     }
+  svn_pool_destroy(iterpool);
 
   return svn_error_trace(cb_err);
 }
@@ -356,6 +371,7 @@ svn_fs_base__unlock(svn_fs_t *fs,
 {
   apr_hash_index_t *hi;
   svn_error_t *cb_err = SVN_NO_ERROR;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
@@ -366,16 +382,18 @@ svn_fs_base__unlock(svn_fs_t *fs,
       const char *token = apr_hash_this_val(hi);
       svn_error_t *err;
 
+      svn_pool_clear(iterpool);
       args.path = svn_fs__canonicalize_abspath(path, result_pool);
       args.token = token;
       args.break_lock = break_lock;
 
       err = svn_fs_base__retry_txn(fs, txn_body_unlock, &args, TRUE,
-                                   scratch_pool);
+                                   iterpool);
       if (!cb_err && lock_callback)
-        cb_err = lock_callback(lock_baton, path, NULL, err, scratch_pool);
+        cb_err = lock_callback(lock_baton, path, NULL, err, iterpool);
       svn_error_clear(err);
     }
+  svn_pool_destroy(iterpool);
 
   return svn_error_trace(cb_err);
 }

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c Sun Jun 14 20:58:10 2015
@@ -711,6 +711,23 @@ txn_body_begin_txn(void *baton, trail_t
       SVN_ERR(txn_body_change_txn_prop(&cpargs, trail));
     }
 
+  /* Put a datestamp on the newly created txn, so we always know
+     exactly how old it is.  (This will help sysadmins identify
+     long-abandoned txns that may need to be manually removed.) Do
+     this before setting CLIENT_DATE so that it is not recorded as an
+     explicit setting. */
+  {
+    struct change_txn_prop_args cpargs;
+    svn_string_t date;
+    cpargs.fs = trail->fs;
+    cpargs.id = txn_id;
+    cpargs.name = SVN_PROP_REVISION_DATE;
+    date.data  = svn_time_to_cstring(apr_time_now(), trail->pool);
+    date.len = strlen(date.data);
+    cpargs.value = &date;
+    SVN_ERR(txn_body_change_txn_prop(&cpargs, trail));
+  }
+
   if (args->flags & SVN_FS_TXN_CLIENT_DATE)
     {
       struct change_txn_prop_args cpargs;
@@ -737,7 +754,6 @@ svn_fs_base__begin_txn(svn_fs_txn_t **tx
 {
   svn_fs_txn_t *txn;
   struct begin_txn_args args;
-  svn_string_t date;
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
@@ -748,15 +764,7 @@ svn_fs_base__begin_txn(svn_fs_txn_t **tx
 
   *txn_p = txn;
 
-  /* Put a datestamp on the newly created txn, so we always know
-     exactly how old it is.  (This will help sysadmins identify
-     long-abandoned txns that may need to be manually removed.)  When
-     a txn is promoted to a revision, this property will be
-     automatically overwritten with a revision datestamp. */
-  date.data = svn_time_to_cstring(apr_time_now(), pool);
-  date.len = strlen(date.data);
-  return svn_fs_base__change_txn_prop(txn, SVN_PROP_REVISION_DATE,
-                                       &date, pool);
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c Sun Jun 14 20:58:10 2015
@@ -1285,6 +1285,21 @@ base_node_proplist(apr_hash_t **table_p,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+base_node_has_props(svn_boolean_t *has_props,
+                    svn_fs_root_t *root,
+                    const char *path,
+                    apr_pool_t *scratch_pool)
+{
+  apr_hash_t *props;
+
+  SVN_ERR(base_node_proplist(&props, root, path, scratch_pool));
+
+  *has_props = (0 < apr_hash_count(props));
+
+  return SVN_NO_ERROR;
+}
+
 
 struct change_node_prop_args {
   svn_fs_root_t *root;
@@ -1608,13 +1623,15 @@ static svn_error_t *
 base_dir_optimal_order(apr_array_header_t **ordered_p,
                        svn_fs_root_t *root,
                        apr_hash_t *entries,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
   /* 1:1 copy of entries with no differnce in ordering */
   apr_hash_index_t *hi;
-  apr_array_header_t *result = apr_array_make(pool, apr_hash_count(entries),
-                                              sizeof(svn_fs_dirent_t *));
-  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
+  apr_array_header_t *result
+    = apr_array_make(result_pool, apr_hash_count(entries),
+                     sizeof(svn_fs_dirent_t *));
+  for (hi = apr_hash_first(scratch_pool, entries); hi; hi = apr_hash_next(hi))
     APR_ARRAY_PUSH(result, svn_fs_dirent_t *) = apr_hash_this_val(hi);
 
   *ordered_p = result;
@@ -3164,7 +3181,8 @@ txn_body_copy(void *baton,
   if ((to_parent_path->node)
       && (svn_fs_base__id_compare(svn_fs_base__dag_get_id(from_node),
                                   svn_fs_base__dag_get_id
-                                  (to_parent_path->node)) == svn_fs_node_same))
+                                  (to_parent_path->node))
+          == svn_fs_node_unchanged))
     return SVN_NO_ERROR;
 
   if (! from_root->is_txn_root)
@@ -5489,6 +5507,7 @@ static root_vtable_t root_vtable = {
   base_closest_copy,
   base_node_prop,
   base_node_proplist,
+  base_node_has_props,
   base_change_node_prop,
   base_props_changed,
   base_dir_entries,



Mime
View raw message