subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danie...@apache.org
Subject svn commit: r1705385 - in /subversion/branches/patch-exec: ./ subversion/include/ subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_fs_x/ subversion/libsvn_ra_serf/ subversion/libsvn...
Date Fri, 25 Sep 2015 23:27:01 GMT
Author: danielsh
Date: Fri Sep 25 23:26:59 2015
New Revision: 1705385

URL: http://svn.apache.org/viewvc?rev=1705385&view=rev
Log:
On the patch-exec branch, sync with trunk@1705384.

* subversion/libsvn_client/patch.c
  (init_patch_target): Update for removal of 'has_prop_changes' local variable.

Modified:
    subversion/branches/patch-exec/   (props changed)
    subversion/branches/patch-exec/subversion/include/svn_dav.h
    subversion/branches/patch-exec/subversion/libsvn_client/client.h
    subversion/branches/patch-exec/subversion/libsvn_client/patch.c
    subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c
    subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c
    subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c
    subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c
    subversion/branches/patch-exec/subversion/libsvn_fs_x/   (props changed)
    subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c
    subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c
    subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h
    subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c
    subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c
    subversion/branches/patch-exec/subversion/libsvn_subr/auth.c
    subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c
    subversion/branches/patch-exec/subversion/mod_dav_svn/version.c
    subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py
    subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c
    subversion/branches/patch-exec/tools/dist/backport/merger.py
    subversion/branches/patch-exec/tools/dist/backport/status.py

Propchange: subversion/branches/patch-exec/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Sep 25 23:26:59 2015
@@ -94,4 +94,4 @@
 /subversion/branches/verify-at-commit:1462039-1462408
 /subversion/branches/verify-keep-going:1439280-1546110
 /subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1692717-1704588
+/subversion/trunk:1692717-1705384

Modified: subversion/branches/patch-exec/subversion/include/svn_dav.h
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/include/svn_dav.h?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/include/svn_dav.h (original)
+++ subversion/branches/patch-exec/subversion/include/svn_dav.h Fri Sep 25 23:26:59 2015
@@ -386,6 +386,15 @@ extern "C" {
 #define SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS\
             SVN_DAV_PROP_NS_DAV "svn/reverse-file-revs"
 
+/** Presence of this in a DAV header in an OPTIONS response indicates
+ * that the transmitter (in this case, the server) knows how to handle
+ * svndiff1 format encoding.
+ *
+ * @since New in 1.10.
+ */
+#define SVN_DAV_NS_DAV_SVN_SVNDIFF1\
+            SVN_DAV_PROP_NS_DAV "svn/svndiff1"
+
 
 /** @} */
 

Modified: subversion/branches/patch-exec/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_client/client.h?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_client/client.h (original)
+++ subversion/branches/patch-exec/subversion/libsvn_client/client.h Fri Sep 25 23:26:59 2015
@@ -1072,9 +1072,13 @@ svn_client__ensure_revprop_table(apr_has
    EXPAND_KEYWORDS operates as per the EXPAND argument to
    svn_subst_stream_translated, which see.  If NORMALIZE_EOLS is TRUE and
    LOCAL_ABSPATH requires translation, then normalize the line endings in
-   *NORMAL_STREAM.
+   *NORMAL_STREAM to "\n" if the stream has svn:eol-style set.
 
-   Uses SCRATCH_POOL for temporary allocations. */
+   Note that this IS NOT the repository normal form of the stream as that
+   would use "\r\n" if set to CRLF and "\r" if set to CR.
+
+   The stream is allocated in RESULT_POOL and temporary SCRATCH_POOL is
+   used for temporary allocations. */
 svn_error_t *
 svn_client__get_normalized_stream(svn_stream_t **normal_stream,
                                   svn_wc_context_t *wc_ctx,

Modified: subversion/branches/patch-exec/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_client/patch.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_client/patch.c Fri Sep 25 23:26:59 2015
@@ -380,7 +380,7 @@ obtain_eol_and_keywords_for_file(apr_has
 static svn_error_t *
 resolve_target_path(patch_target_t *target,
                     const char *path_from_patchfile,
-                    const char *wcroot_abspath,
+                    const char *root_abspath,
                     int strip_count,
                     svn_boolean_t has_text_changes,
                     svn_wc_context_t *wc_ctx,
@@ -413,7 +413,7 @@ resolve_target_path(patch_target_t *targ
 
   if (svn_dirent_is_absolute(stripped_path))
     {
-      target->local_relpath = svn_dirent_is_child(wcroot_abspath,
+      target->local_relpath = svn_dirent_is_child(root_abspath,
                                                   stripped_path,
                                                   result_pool);
 
@@ -433,9 +433,9 @@ resolve_target_path(patch_target_t *targ
     }
 
   /* Make sure the path is secure to use. We want the target to be inside
-   * of the working copy and not be fooled by symlinks it might contain. */
+   * the locked tree and not be fooled by symlinks it might contain. */
   SVN_ERR(svn_dirent_is_under_root(&under_root,
-                                   &target->local_abspath, wcroot_abspath,
+                                   &target->local_abspath, root_abspath,
                                    target->local_relpath, result_pool));
 
   if (! under_root)
@@ -486,19 +486,23 @@ resolve_target_path(patch_target_t *targ
   if (target->locally_deleted)
     {
       const char *moved_to_abspath;
+      const char *op_root_abspath;
 
-      SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
+      SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, &op_root_abspath,
                                           wc_ctx, target->local_abspath,
                                           result_pool, scratch_pool));
-      /* ### BUG: moved_to_abspath contains the target where the op-root was
-         ### moved to... not the target itself! */
       if (moved_to_abspath)
         {
           target->local_abspath = moved_to_abspath;
-          target->local_relpath = svn_dirent_skip_ancestor(wcroot_abspath,
-                                                          moved_to_abspath);
-          SVN_ERR_ASSERT(target->local_relpath &&
-                         target->local_relpath[0] != '\0');
+          target->local_relpath = svn_dirent_skip_ancestor(root_abspath,
+                                                           moved_to_abspath);
+
+          if (!target->local_relpath || target->local_relpath[0] == '\0')
+            {
+              /* The target path is outside of the patch area. Skip it. */
+              target->skipped = TRUE;
+              return SVN_NO_ERROR;
+            }
 
           /* As far as we are concerned this target is not locally deleted. */
           target->locally_deleted = FALSE;
@@ -544,7 +548,7 @@ readline_prop(void *baton, svn_stringbuf
               svn_boolean_t *eof, apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
 {
-  prop_read_baton_t *b = (prop_read_baton_t *)baton;
+  prop_read_baton_t *b = baton;
   svn_stringbuf_t *str = NULL;
   const char *c;
   svn_boolean_t found_eof;
@@ -609,7 +613,8 @@ readline_prop(void *baton, svn_stringbuf
 static svn_error_t *
 tell_prop(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool)
 {
-  prop_read_baton_t *b = (prop_read_baton_t *)baton;
+  prop_read_baton_t *b = baton;
+
   *offset = b->offset;
   return SVN_NO_ERROR;
 }
@@ -619,7 +624,8 @@ tell_prop(void *baton, apr_off_t *offset
 static svn_error_t *
 seek_prop(void *baton, apr_off_t offset, apr_pool_t *scratch_pool)
 {
-  prop_read_baton_t *b = (prop_read_baton_t *)baton;
+  prop_read_baton_t *b = baton;
+
   b->offset = offset;
   return SVN_NO_ERROR;
 }
@@ -630,7 +636,8 @@ static svn_error_t *
 write_prop(void *baton, const char *buf, apr_size_t len,
            apr_pool_t *scratch_pool)
 {
-  svn_stringbuf_t *patched_value = (svn_stringbuf_t *)baton;
+  svn_stringbuf_t *patched_value = baton;
+
   svn_stringbuf_appendbytes(patched_value, buf, len);
   return SVN_NO_ERROR;
 }
@@ -720,71 +727,15 @@ readline_file(void *baton, svn_stringbuf
               svn_boolean_t *eof, apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
 {
-  apr_file_t *file = (apr_file_t *)baton;
-  svn_stringbuf_t *str = NULL;
-  apr_size_t numbytes;
-  char c;
-  svn_boolean_t found_eof;
+  apr_file_t *file = baton;
 
-  /* Read bytes into STR up to and including, but not storing,
-   * the next EOL sequence. */
-  *eol_str = NULL;
-  numbytes = 1;
-  found_eof = FALSE;
-  while (!found_eof)
-    {
-      SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
-                                     &found_eof, scratch_pool));
-      if (numbytes != 1)
-        {
-          found_eof = TRUE;
-          break;
-        }
-
-      if (c == '\n')
-        {
-          *eol_str = "\n";
-        }
-      else if (c == '\r')
-        {
-          *eol_str = "\r";
+  SVN_ERR(svn_io_file_readline(file, line, eol_str, eof, APR_SIZE_MAX,
+                               result_pool, scratch_pool));
 
-          if (!found_eof)
-            {
-              apr_off_t pos;
-
-              /* Check for "\r\n" by peeking at the next byte. */
-              pos = 0;
-              SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
-              SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
-                                             &found_eof, scratch_pool));
-              if (numbytes == 1 && c == '\n')
-                {
-                  *eol_str = "\r\n";
-                }
-              else
-                {
-                  /* Pretend we never peeked. */
-                  SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
-                  found_eof = FALSE;
-                  numbytes = 1;
-                }
-            }
-        }
-      else
-        {
-          if (str == NULL)
-            str = svn_stringbuf_create_ensure(80, result_pool);
-          svn_stringbuf_appendbyte(str, c);
-        }
-
-      if (*eol_str)
-        break;
-    }
-
-  if (eof)
-    *eof = found_eof;
-  *line = str;
+  if (!(*line)->len)
+    *line = NULL;
+  else
+    *eof = FALSE;
 
   return SVN_NO_ERROR;
 }
@@ -795,7 +746,8 @@ readline_file(void *baton, svn_stringbuf
 static svn_error_t *
 tell_file(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool)
 {
-  apr_file_t *file = (apr_file_t *)baton;
+  apr_file_t *file = baton;
+
   *offset = 0;
   SVN_ERR(svn_io_file_seek(file, APR_CUR, offset, scratch_pool));
   return SVN_NO_ERROR;
@@ -806,7 +758,8 @@ tell_file(void *baton, apr_off_t *offset
 static svn_error_t *
 seek_file(void *baton, apr_off_t offset, apr_pool_t *scratch_pool)
 {
-  apr_file_t *file = (apr_file_t *)baton;
+  apr_file_t *file = baton;
+
   SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, scratch_pool));
   return SVN_NO_ERROR;
 }
@@ -817,7 +770,8 @@ static svn_error_t *
 write_file(void *baton, const char *buf, apr_size_t len,
            apr_pool_t *scratch_pool)
 {
-  apr_file_t *file = (apr_file_t *)baton;
+  apr_file_t *file = baton;
+
   SVN_ERR(svn_io_file_write_full(file, buf, len, &len, scratch_pool));
   return SVN_NO_ERROR;
 }
@@ -1010,7 +964,7 @@ contradictory_executability(const svn_pa
 static svn_error_t *
 init_patch_target(patch_target_t **patch_target,
                   const svn_patch_t *patch,
-                  const char *wcroot_abspath,
+                  const char *root_abspath,
                   svn_wc_context_t *wc_ctx, int strip_count,
                   svn_boolean_t remove_tempfiles,
                   apr_pool_t *result_pool, apr_pool_t *scratch_pool)
@@ -1018,25 +972,6 @@ init_patch_target(patch_target_t **patch
   patch_target_t *target;
   target_content_t *content;
   svn_boolean_t has_text_changes = FALSE;
-  svn_boolean_t has_prop_changes = FALSE;
-
-  {
-    apr_hash_index_t *hi;
-
-    for (hi = apr_hash_first(scratch_pool, patch->prop_patches);
-         hi;
-         hi = apr_hash_next(hi))
-      {
-        svn_prop_patch_t *prop_patch = apr_hash_this_val(hi);
-        if (! has_prop_changes)
-          has_prop_changes = prop_patch->hunks->nelts > 0;
-        else
-          break;
-      }
-  }
-
-  if (patch->new_executable_p != svn_tristate_unknown)
-    has_prop_changes = TRUE;
 
   has_text_changes = ((patch->hunks && patch->hunks->nelts > 0)
                       || patch->binary_patch);
@@ -1057,9 +992,12 @@ init_patch_target(patch_target_t **patch
   target->kind_on_disk = svn_node_none;
   target->content = content;
   target->prop_targets = apr_hash_make(result_pool);
+  if (patch->new_executable_p != svn_tristate_unknown)
+    /* May also be set by apply_hunk(). */
+    target->has_prop_changes = TRUE;
 
   SVN_ERR(resolve_target_path(target, choose_target_filename(patch),
-                              wcroot_abspath, strip_count, has_text_changes,
+                              root_abspath, strip_count, has_text_changes,
                               wc_ctx, result_pool, scratch_pool));
   *patch_target = target;
   if (! target->skipped)
@@ -1137,7 +1075,7 @@ init_patch_target(patch_target_t **patch
 
           if (svn_dirent_is_absolute(move_target_path))
             {
-              move_target_relpath = svn_dirent_is_child(wcroot_abspath,
+              move_target_relpath = svn_dirent_is_child(root_abspath,
                                                         move_target_path,
                                                         scratch_pool);
               if (! move_target_relpath)
@@ -1155,7 +1093,7 @@ init_patch_target(patch_target_t **patch
           /* Make sure the move target path is secure to use. */
           SVN_ERR(svn_dirent_is_under_root(&under_root,
                                            &target->move_target_abspath,
-                                           wcroot_abspath,
+                                           root_abspath,
                                            move_target_relpath, result_pool));
           if (! under_root)
             {
@@ -2397,7 +2335,6 @@ apply_one_patch(patch_target_t **patch_t
   apr_hash_index_t *hash_index;
   svn_linenum_t previous_offset = 0;
   svn_boolean_t has_text_changes = FALSE;
-  svn_boolean_t has_prop_changes = FALSE;
 
   SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count,
                             remove_tempfiles, result_pool, scratch_pool));
@@ -2501,32 +2438,49 @@ apply_one_patch(patch_target_t **patch_t
     }
   else if (patch->binary_patch)
     {
-#ifdef SVN_DEBUG
-      svn_stream_t *tmp;
-
-      /* ### Dummy code that just reads the two streams in the patch file */
-      tmp = svn_diff_get_binary_diff_result_stream(patch->binary_patch,
-                                                   iterpool);
+      svn_stream_t *orig_stream;
+      svn_boolean_t same;
 
-      SVN_ERR(svn_stream_copy3(tmp, svn_stream_empty(iterpool),
-                               NULL, NULL,
-                               iterpool));
+      if (target->file)
+        orig_stream = svn_stream_from_aprfile2(target->file, TRUE, iterpool);
+      else
+        orig_stream = svn_stream_empty(iterpool);
 
-      tmp = svn_diff_get_binary_diff_original_stream(patch->binary_patch,
-                                                     iterpool);
+      SVN_ERR(svn_stream_contents_same2(
+                &same, orig_stream,
+                svn_diff_get_binary_diff_original_stream(patch->binary_patch,
+                                                         iterpool),
+                iterpool));
+      svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_stream_copy3(tmp, svn_stream_empty(iterpool),
-                               NULL, NULL,
-                               iterpool));
+      if (same)
+        {
+          /* The file in the working copy is identical to the one expected by
+             the patch... So we can write the result stream; no fuzz,
+             just a 100% match */
+
+          SVN_ERR(svn_stream_copy3(
+                svn_diff_get_binary_diff_result_stream(patch->binary_patch,
+                                                       iterpool),
+                svn_stream_from_aprfile2(target->patched_file, TRUE,
+                                         iterpool),
+                cancel_func, cancel_baton,
+                iterpool));
 
-      /* ### TODO:
-          - write the patched version and set has_text_changes = TRUE;
-          - or: write+notify rejection
-          - or: set skip (which also skips property changes)
+          has_text_changes = TRUE;
+          target->has_text_changes = TRUE;
+        }
+      else
+        {
+          /* ### TODO: Implement a proper reject of a binary patch
 
-         Doing nothing just ignores the patchset (<= 1.9.x behaviour)
-       */
-#endif
+             This should at least setup things for a proper notification,
+             and perhaps install a normal text conflict. Unlike normal unified
+             diff based patches we have all the versions we would need for
+             that in a much easier format than can be obtained from the patch
+             file. */
+          target->skipped = TRUE;
+        }
     }
   else if (target->move_target_abspath)
     {
@@ -2545,12 +2499,12 @@ apply_one_patch(patch_target_t **patch_t
           /* Copy any remaining lines to target. (read: all lines) */
           SVN_ERR(copy_lines_to_target(target->content, 0, scratch_pool));
           if (!target->content->eof)
-          {
-            /* We could not copy the entire target file to the temporary
-            * file, and would truncate the target if we copied the
-            * temporary file on top of it. Skip this target. */
-            target->skipped = TRUE;
-          }
+            {
+              /* We could not copy the entire target file to the temporary
+               * file, and would truncate the target if we copied the
+               * temporary file on top of it. Skip this target. */
+              target->skipped = TRUE;
+            }
           has_text_changes = TRUE;
         }
     }
@@ -2570,8 +2524,6 @@ apply_one_patch(patch_target_t **patch_t
       if (! strcmp(prop_name, SVN_PROP_SPECIAL))
         target->is_special = TRUE;
 
-      has_prop_changes = TRUE;
-
       /* We'll store matched hunks in prop_content. */
       prop_target = svn_hash_gets(target->prop_targets, prop_name);
 
@@ -2765,6 +2717,9 @@ apply_one_patch(patch_target_t **patch_t
 /* Try to create missing parent directories for TARGET in the working copy
  * rooted at ABS_WC_PATH, and add the parents to version control.
  * If the parents cannot be created, mark the target as skipped.
+ *
+ * In dry run mode record missing parents in ALREADY_ADDED
+ *
  * Use client context CTX. If DRY_RUN is true, do not create missing
  * parents but issue notifications only.
  * Use SCRATCH_POOL for temporary allocations. */
@@ -2773,6 +2728,7 @@ create_missing_parents(patch_target_t *t
                        const char *abs_wc_path,
                        svn_client_ctx_t *ctx,
                        svn_boolean_t dry_run,
+                       apr_hash_t *already_added,
                        apr_pool_t *scratch_pool)
 {
   const char *local_abspath;
@@ -2861,17 +2817,25 @@ create_missing_parents(patch_target_t *t
                                           scratch_pool);
           if (dry_run)
             {
-              if (ctx->notify_func2)
+              if (!svn_hash_gets(already_added, local_abspath))
                 {
-                  /* Just do notification. */
-                  svn_wc_notify_t *notify;
-                  notify = svn_wc_create_notify(local_abspath,
-                                                svn_wc_notify_add,
-                                                iterpool);
-                  notify->kind = svn_node_dir;
-                  ctx->notify_func2(ctx->notify_baton2, notify,
-                                    iterpool);
-                }
+                  svn_hash_sets(already_added,
+                                apr_pstrdup(apr_hash_pool_get(already_added),
+                                            local_abspath),
+                                "");
+
+                  if (ctx->notify_func2)
+                    {
+                      /* Just do notification. */
+                      svn_wc_notify_t *notify;
+                      notify = svn_wc_create_notify(local_abspath,
+                                                    svn_wc_notify_add,
+                                                    iterpool);
+                      notify->kind = svn_node_dir;
+                      ctx->notify_func2(ctx->notify_baton2, notify,
+                                        iterpool);
+                    }
+              }
             }
           else
             {
@@ -2898,12 +2862,17 @@ create_missing_parents(patch_target_t *t
 
 /* Install a patched TARGET into the working copy at ABS_WC_PATH.
  * Use client context CTX to retrieve WC_CTX, and possibly doing
- * notifications. If DRY_RUN is TRUE, don't modify the working copy.
+ * notifications.
+ *
+ * Pass on ALREADY_ADDED to allow recording already added ancestors
+ * in dry-run mode.
+ *
+ * If DRY_RUN is TRUE, don't modify the working copy.
  * Do temporary allocations in POOL. */
 static svn_error_t *
 install_patched_target(patch_target_t *target, const char *abs_wc_path,
                        svn_client_ctx_t *ctx, svn_boolean_t dry_run,
-                       apr_pool_t *pool)
+                       apr_hash_t *already_added, apr_pool_t *pool)
 {
   if (target->deleted)
     {
@@ -2952,7 +2921,7 @@ install_patched_target(patch_target_t *t
             }
           else
             SVN_ERR(create_missing_parents(target, abs_wc_path, ctx,
-                                           dry_run, pool));
+                                           dry_run, already_added, pool));
 
         }
       else
@@ -3350,7 +3319,7 @@ static svn_error_t *
 apply_patches(/* The path to the patch file. */
               const char *patch_abspath,
               /* The abspath to the working copy the patch should be applied to. */
-              const char *abs_wc_path,
+              const char *root_abspath,
               /* Indicates whether we're doing a dry run. */
               svn_boolean_t dry_run,
               /* Number of leading components to strip from patch target paths. */
@@ -3372,6 +3341,7 @@ apply_patches(/* The path to the patch f
   apr_pool_t *iterpool;
   svn_patch_file_t *patch_file;
   apr_array_header_t *targets_info;
+  apr_hash_t *already_added = apr_hash_make(scratch_pool);
 
   /* Try to open the patch file. */
   SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, scratch_pool));
@@ -3394,7 +3364,7 @@ apply_patches(/* The path to the patch f
         {
           patch_target_t *target;
 
-          SVN_ERR(apply_one_patch(&target, patch, abs_wc_path,
+          SVN_ERR(apply_one_patch(&target, patch, root_abspath,
                                   ctx->wc_ctx, strip_count,
                                   ignore_whitespace, remove_tempfiles,
                                   patch_func, patch_baton,
@@ -3418,21 +3388,28 @@ apply_patches(/* The path to the patch f
                       || target->added
                       || target->move_target_abspath
                       || target->deleted)
-                    SVN_ERR(install_patched_target(target, abs_wc_path,
-                                                   ctx, dry_run, iterpool));
+                    SVN_ERR(install_patched_target(target, root_abspath,
+                                                   ctx, dry_run,
+                                                   already_added, iterpool));
 
                   if (target->has_prop_changes && (!target->deleted))
                     SVN_ERR(install_patched_prop_targets(target, ctx,
                                                          dry_run, iterpool));
 
                   SVN_ERR(write_out_rejected_hunks(target, dry_run, iterpool));
+
+                  if (target->added)
+                    svn_hash_sets(already_added,
+                                  apr_pstrdup(scratch_pool,
+                                              target->local_abspath),
+                                  "");
                 }
               SVN_ERR(send_patch_notification(target, ctx, iterpool));
 
               if (target->deleted && !target->skipped)
                 {
                   SVN_ERR(check_ancestor_delete(target_info->local_abspath,
-                                                targets_info, abs_wc_path,
+                                                targets_info, root_abspath,
                                                 dry_run, ctx,
                                                 scratch_pool, iterpool));
                 }

Modified: subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_diff/binary_diff.c Fri Sep 25 23:26:59 2015
@@ -115,7 +115,7 @@ svn_diff__base85_decode_line(char *outpu
                              apr_pool_t *scratch_pool)
 {
   {
-    apr_size_t expected_data = (output_len + 3) / 4 * 5;
+    apr_ssize_t expected_data = (output_len + 3) / 4 * 5;
 
     if (base85_len != expected_data)
       return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL,

Modified: subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_diff/parse-diff.c Fri Sep 25 23:26:59 2015
@@ -85,6 +85,10 @@ struct svn_diff_hunk_t {
   /* Number of lines of leading and trailing hunk context. */
   svn_linenum_t leading_context;
   svn_linenum_t trailing_context;
+
+  /* Did we see a 'file does not end with eol' marker in this hunk? */
+  svn_boolean_t original_no_final_eol;
+  svn_boolean_t modified_no_final_eol;
 };
 
 struct svn_diff_binary_patch_t {
@@ -623,7 +627,8 @@ parse_hunk_header(const char *header, sv
  * 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.
+ * is being read. NO_FINAL_EOL declares if the hunk contains a no final
+ * EOL marker.
  *
  * All other parameters are as in svn_diff_hunk_readline_original_text()
  * and svn_diff_hunk_readline_modified_text().
@@ -635,6 +640,7 @@ hunk_readline_original_or_modified(apr_f
                                    const char **eol,
                                    svn_boolean_t *eof,
                                    char verboten,
+                                   svn_boolean_t no_final_eol,
                                    apr_pool_t *result_pool,
                                    apr_pool_t *scratch_pool)
 {
@@ -642,13 +648,16 @@ hunk_readline_original_or_modified(apr_f
   svn_boolean_t filtered;
   apr_off_t pos;
   svn_stringbuf_t *str;
+  const char *eol_p;
+
+  if (!eol)
+    eol = &eol_p;
 
   if (range->current >= range->end)
     {
       /* We're past the range. Indicate that no bytes can be read. */
       *eof = TRUE;
-      if (eol)
-        *eol = NULL;
+      *eol = NULL;
       *stringbuf = svn_stringbuf_create_empty(result_pool);
       return SVN_NO_ERROR;
     }
@@ -671,6 +680,7 @@ hunk_readline_original_or_modified(apr_f
     {
       /* EOF, return an empty string. */
       *stringbuf = svn_stringbuf_create_ensure(0, result_pool);
+      *eol = NULL;
     }
   else if (str->data[0] == '+' || str->data[0] == '-' || str->data[0] == ' ')
     {
@@ -679,10 +689,34 @@ hunk_readline_original_or_modified(apr_f
     }
   else
     {
-      /* Return the line as-is. */
+      /* Return the line as-is. Handle as a chopped leading spaces */
       *stringbuf = svn_stringbuf_dup(str, result_pool);
     }
 
+  if (!filtered && *eof && !*eol && !no_final_eol && *str->data)
+    {
+      /* Ok, we miss a final EOL in the patch file, but didn't see a
+         no eol marker line.
+
+         We should report that we had an EOL or the patch code will
+         misbehave (and it knows nothing about no eol markers) */
+
+      if (eol != &eol_p)
+        {
+          apr_off_t start = 0;
+
+          SVN_ERR(svn_io_file_seek(file, APR_SET, &start, scratch_pool));
+
+          SVN_ERR(svn_io_file_readline(file, &str, eol, NULL, APR_SIZE_MAX,
+                                       scratch_pool, scratch_pool));
+
+          /* Every patch file that has hunks has at least one EOL*/
+          SVN_ERR_ASSERT(*eol != NULL);
+        }
+
+      *eof = FALSE;
+      /* Fall through to seek back to the right location */
+    }
   SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -703,6 +737,9 @@ svn_diff_hunk_readline_original_text(svn
                                          &hunk->original_text_range,
                                        stringbuf, eol, eof,
                                        hunk->patch->reverse ? '-' : '+',
+                                       hunk->patch->reverse
+                                          ? hunk->modified_no_final_eol
+                                          : hunk->original_no_final_eol,
                                        result_pool, scratch_pool));
 }
 
@@ -721,6 +758,9 @@ svn_diff_hunk_readline_modified_text(svn
                                          &hunk->modified_text_range,
                                        stringbuf, eol, eof,
                                        hunk->patch->reverse ? '+' : '-',
+                                       hunk->patch->reverse
+                                          ? hunk->original_no_final_eol
+                                          : hunk->modified_no_final_eol,
                                        result_pool, scratch_pool));
 }
 
@@ -735,13 +775,16 @@ svn_diff_hunk_readline_diff_text(svn_dif
   svn_stringbuf_t *line;
   apr_size_t max_len;
   apr_off_t pos;
+  const char *eol_p;
+
+  if (!eol)
+    eol = &eol_p;
 
   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;
+      *eol = NULL;
       *stringbuf = svn_stringbuf_create_empty(result_pool);
       return SVN_NO_ERROR;
     }
@@ -757,6 +800,37 @@ svn_diff_hunk_readline_diff_text(svn_dif
   hunk->diff_text_range.current = 0;
   SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR,
                            &hunk->diff_text_range.current, scratch_pool));
+
+  if (*eof && !*eol && *line->data)
+    {
+      /* Ok, we miss a final EOL in the patch file, but didn't see a
+          no eol marker line.
+
+          We should report that we had an EOL or the patch code will
+          misbehave (and it knows nothing about no eol markers) */
+
+      if (eol != &eol_p)
+        {
+          /* Lets pick the first eol we find in our patch file */
+          apr_off_t start = 0;
+          svn_stringbuf_t *str;
+
+          SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &start,
+                                   scratch_pool));
+
+          SVN_ERR(svn_io_file_readline(hunk->apr_file, &str, eol, NULL,
+                                       APR_SIZE_MAX,
+                                       scratch_pool, scratch_pool));
+
+          /* Every patch file that has hunks has at least one EOL*/
+          SVN_ERR_ASSERT(*eol != NULL);
+        }
+
+      *eof = FALSE;
+
+      /* Fall through to seek back to the right location */
+    }
+
   SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &pos, scratch_pool));
 
   if (hunk->patch->reverse)
@@ -963,6 +1037,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
   apr_off_t start, end;
   apr_off_t original_end;
   apr_off_t modified_end;
+  svn_boolean_t original_no_final_eol = FALSE;
+  svn_boolean_t modified_no_final_eol = FALSE;
   svn_linenum_t original_lines;
   svn_linenum_t modified_lines;
   svn_linenum_t leading_context;
@@ -1060,6 +1136,11 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
 
               SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool));
             }
+          /* Set for the type and context by using != the other type */
+          if (last_line_type != modified_line)
+            original_no_final_eol = TRUE;
+          if (last_line_type != original_line)
+            modified_no_final_eol = TRUE;
 
           continue;
         }
@@ -1187,14 +1268,16 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
               SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ",
                                       result_pool));
               if (*prop_name)
-                *prop_operation = svn_diff_op_added;
+                *prop_operation = (patch->reverse ? svn_diff_op_deleted
+                                                  : svn_diff_op_added);
             }
           else if (starts_with(line->data, "Deleted: "))
             {
               SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ",
                                       result_pool));
               if (*prop_name)
-                *prop_operation = svn_diff_op_deleted;
+                *prop_operation = (patch->reverse ? svn_diff_op_added
+                                                  : svn_diff_op_deleted);
             }
           else if (starts_with(line->data, "Modified: "))
             {
@@ -1235,6 +1318,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       (*hunk)->modified_text_range.start = start;
       (*hunk)->modified_text_range.current = start;
       (*hunk)->modified_text_range.end = modified_end;
+      (*hunk)->original_no_final_eol = original_no_final_eol;
+      (*hunk)->modified_no_final_eol = modified_no_final_eol;
     }
   else
     /* Something went wrong, just discard the result. */
@@ -1793,6 +1878,7 @@ parse_hunks(svn_patch_t *patch, apr_file
 
 static svn_error_t *
 parse_binary_patch(svn_patch_t *patch, apr_file_t *apr_file,
+                   svn_boolean_t reverse,
                    apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -1826,7 +1912,7 @@ parse_binary_patch(svn_patch_t *patch, a
           char c = line->data[0];
 
           /* 66 = len byte + (52/4*5) chars */
-          if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') 
+          if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
               && line->len <= 66
               && !strchr(line->data, ':')
               && !strchr(line->data, ' '))
@@ -1893,6 +1979,22 @@ parse_binary_patch(svn_patch_t *patch, a
       patch->binary_patch = bpatch; /* SUCCESS */
     }
 
+  /* Reverse patch if requested */
+  if (reverse && patch->binary_patch)
+    {
+      apr_off_t tmp_start = bpatch->src_start;
+      apr_off_t tmp_end = bpatch->src_end;
+      svn_filesize_t tmp_filesize = bpatch->src_filesize;
+
+      bpatch->src_start = bpatch->dst_start;
+      bpatch->src_end = bpatch->dst_end;
+      bpatch->src_filesize = bpatch->dst_filesize;
+
+      bpatch->dst_start = tmp_start;
+      bpatch->dst_end = tmp_end;
+      bpatch->dst_filesize = tmp_filesize;
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1924,6 +2026,7 @@ static struct transition transitions[] =
   {"deleted file ",     state_git_diff_seen,    git_deleted_file},
 
   {"GIT binary patch",  state_git_diff_seen,    binary_patch_start},
+  {"GIT binary patch",  state_git_tree_seen,    binary_patch_start},
 };
 
 svn_error_t *
@@ -2038,6 +2141,22 @@ svn_diff_parse_next_patch(svn_patch_t **
       temp = patch->old_filename;
       patch->old_filename = patch->new_filename;
       patch->new_filename = temp;
+
+      switch (patch->operation)
+        {
+          case svn_diff_op_added:
+            patch->operation = svn_diff_op_deleted;
+            break;
+          case svn_diff_op_deleted:
+            patch->operation = svn_diff_op_added;
+            break;
+
+          /* ### case svn_diff_op_copied:
+             ### case svn_diff_op_moved:*/
+
+          case svn_diff_op_modified:
+            break; /* Stays modify */
+        }
     }
 
   if (patch->old_filename == NULL || patch->new_filename == NULL)
@@ -2049,7 +2168,7 @@ svn_diff_parse_next_patch(svn_patch_t **
     {
       if (state == state_binary_patch_found)
         {
-          SVN_ERR(parse_binary_patch(patch, patch_file->apr_file,
+          SVN_ERR(parse_binary_patch(patch, patch_file->apr_file, reverse,
                                      result_pool, iterpool));
           /* And fall through in property parsing */
         }

Modified: subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_fs_base/lock.c Fri Sep 25 23:26:59 2015
@@ -108,7 +108,7 @@ txn_body_lock(void *baton, trail_t *trai
   SVN_ERR(svn_fs_base__get_path_kind(&kind, args->path, trail, trail->pool));
 
   /* Until we implement directory locks someday, we only allow locks
-     on files or non-existent paths. */
+     on files. */
   if (kind == svn_node_dir)
     return SVN_FS__ERR_NOT_FILE(trail->fs, args->path);
 

Modified: subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_fs_fs/lock.c Fri Sep 25 23:26:59 2015
@@ -847,7 +847,7 @@ lock_body(void *baton, apr_pool_t *pool)
   apr_pool_t *iterpool = svn_pool_create(pool);
 
   /* Until we implement directory locks someday, we only allow locks
-     on files or non-existent paths. */
+     on files. */
   /* Use fs->vtable->foo instead of svn_fs_foo to avoid circular
      library dependencies, which are not portable. */
   SVN_ERR(lb->fs->vtable->youngest_rev(&youngest, lb->fs, pool));

Propchange: subversion/branches/patch-exec/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Sep 25 23:26:59 2015
@@ -93,4 +93,4 @@
 /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
 /subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1653608,
 1658482
-/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1692717-1704588
+/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1692717-1705384

Modified: subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_fs_x/lock.c Fri Sep 25 23:26:59 2015
@@ -868,7 +868,7 @@ lock_body(void *baton,
   apr_pool_t *iterpool = svn_pool_create(pool);
 
   /* Until we implement directory locks someday, we only allow locks
-     on files or non-existent paths. */
+     on files. */
   /* Use fs->vtable->foo instead of svn_fs_foo to avoid circular
      library dependencies, which are not portable. */
   SVN_ERR(lb->fs->vtable->youngest_rev(&youngest, lb->fs, pool));

Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/options.c Fri Sep 25 23:26:59 2015
@@ -226,6 +226,12 @@ capabilities_headers_iterator_callback(v
         {
           session->supports_rev_rsrc_replay = TRUE;
         }
+      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF1, vals))
+        {
+          /* Use compressed svndiff1 format for servers that properly
+             advertise this capability (Subversion 1.10 and greater). */
+          session->supports_svndiff1 = TRUE;
+        }
     }
 
   /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
@@ -243,7 +249,8 @@ capabilities_headers_iterator_callback(v
           apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1);
         }
 
-      /* Use compressed svndiff1 format for servers that speak HTTPv2.
+      /* Use compressed svndiff1 format for servers that speak HTTPv2,
+         in addition to servers that send SVN_DAV_NS_DAV_SVN_SVNDIFF1.
 
          Apache HTTPd + mod_dav_svn servers support svndiff1, beginning
          from Subversion 1.4, but they do not advertise this capability.

Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/ra_serf.h Fri Sep 25 23:26:59 2015
@@ -1548,6 +1548,17 @@ svn_ra_serf__create_bucket_with_eagain(c
                                        apr_size_t len,
                                        serf_bucket_alloc_t *allocator);
 
+/* Parse a given URL_STR, fill in all supplied fields of URI
+ * structure.
+ *
+ * This function is a compatibility wrapper around apr_uri_parse().
+ * Different apr-util versions set apr_uri_t.path to either NULL or ""
+ * for root paths, and serf expects to see "/". This function always
+ * sets URI.path to "/" for these paths. */
+svn_error_t *
+svn_ra_serf__uri_parse(apr_uri_t *uri,
+                       const char *url_str,
+                       apr_pool_t *result_pool);
 
 
 #if defined(SVN_DEBUG)

Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/serf.c Fri Sep 25 23:26:59 2015
@@ -64,7 +64,7 @@ ra_serf_version(void)
 
 #define RA_SERF_DESCRIPTION_VER \
     N_("Module for accessing a repository via WebDAV protocol using serf.\n" \
-       "  - using serf %d.%d.%d")
+       "  - using serf %d.%d.%d (compiled with %d.%d.%d)")
 
 /* Implements svn_ra__vtable_t.get_description(). */
 static const char *
@@ -73,7 +73,12 @@ ra_serf_get_description(apr_pool_t *pool
   int major, minor, patch;
 
   serf_lib_version(&major, &minor, &patch);
-  return apr_psprintf(pool, _(RA_SERF_DESCRIPTION_VER), major, minor, patch);
+  return apr_psprintf(pool, _(RA_SERF_DESCRIPTION_VER),
+                      major, minor, patch,
+                      SERF_MAJOR_VERSION,
+                      SERF_MINOR_VERSION,
+                      SERF_PATCH_VERSION
+                      );
 }
 
 /* Implements svn_ra__vtable_t.get_schemes(). */
@@ -508,19 +513,8 @@ svn_ra_serf__open(svn_ra_session_t *sess
                                        serf_sess->pool));
 
 
-  status = apr_uri_parse(serf_sess->pool, session_URL, &url);
-  if (status)
-    {
-      return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                               _("Illegal URL '%s'"),
-                               session_URL);
-    }
-  /* Depending the version of apr-util in use, for root paths url.path
-     will be NULL or "", where serf requires "/". */
-  if (url.path == NULL || url.path[0] == '\0')
-    {
-      url.path = apr_pstrdup(serf_sess->pool, "/");
-    }
+  SVN_ERR(svn_ra_serf__uri_parse(&url, session_URL, serf_sess->pool));
+
   if (!url.port)
     {
       url.port = apr_uri_port_of_scheme(url.scheme);
@@ -740,18 +734,15 @@ ra_serf_dup_session(svn_ra_session_t *ne
 
   new_sess->repos_root_str = apr_pstrdup(result_pool,
                                          new_sess->repos_root_str);
-  status = apr_uri_parse(result_pool, new_sess->repos_root_str,
-                         &new_sess->repos_root);
-  if (status)
-    return svn_ra_serf__wrap_err(status, NULL);
+  SVN_ERR(svn_ra_serf__uri_parse(&new_sess->repos_root,
+                                 new_sess->repos_root_str,
+                                 result_pool));
 
   new_sess->session_url_str = apr_pstrdup(result_pool, new_session_url);
 
-  status = apr_uri_parse(result_pool, new_sess->session_url_str,
-                         &new_sess->session_url);
-
-  if (status)
-    return svn_ra_serf__wrap_err(status, NULL);
+  SVN_ERR(svn_ra_serf__uri_parse(&new_sess->session_url,
+                                 new_sess->session_url_str,
+                                 result_pool));
 
   /* svn_boolean_t supports_inline_props */
   /* supports_rev_rsrc_replay */
@@ -800,7 +791,6 @@ svn_ra_serf__reparent(svn_ra_session_t *
 {
   svn_ra_serf__session_t *session = ra_session->priv;
   apr_uri_t new_url;
-  apr_status_t status;
 
   /* If it's the URL we already have, wave our hands and do nothing. */
   if (strcmp(session->session_url_str, url) == 0)
@@ -822,25 +812,11 @@ svn_ra_serf__reparent(svn_ra_session_t *
             "URL '%s'"), url, session->repos_root_str);
     }
 
-  status = apr_uri_parse(pool, url, &new_url);
-  if (status)
-    {
-      return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                               _("Illegal repository URL '%s'"), url);
-    }
+  SVN_ERR(svn_ra_serf__uri_parse(&new_url, url, pool));
 
-  /* Depending the version of apr-util in use, for root paths url.path
-     will be NULL or "", where serf requires "/". */
   /* ### Maybe we should use a string buffer for these strings so we
      ### don't allocate memory in the session on every reparent? */
-  if (new_url.path == NULL || new_url.path[0] == '\0')
-    {
-      session->session_url.path = apr_pstrdup(session->pool, "/");
-    }
-  else
-    {
-      session->session_url.path = apr_pstrdup(session->pool, new_url.path);
-    }
+  session->session_url.path = apr_pstrdup(session->pool, new_url.path);
   session->session_url_str = apr_pstrdup(session->pool, url);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_ra_serf/util.c Fri Sep 25 23:26:59 2015
@@ -1951,3 +1951,29 @@ svn_ra_serf__create_handler(svn_ra_serf_
   return handler;
 }
 
+svn_error_t *
+svn_ra_serf__uri_parse(apr_uri_t *uri,
+                       const char *url_str,
+                       apr_pool_t *result_pool)
+{
+  apr_status_t status;
+
+  status = apr_uri_parse(result_pool, url_str, uri);
+  if (status)
+    {
+      /* Do not use returned error status in error message because currently
+         apr_uri_parse() returns APR_EGENERAL for all parsing errors. */
+      return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                               _("Illegal URL '%s'"),
+                               url_str);
+    }
+
+  /* Depending the version of apr-util in use, for root paths uri.path
+     will be NULL or "", where serf requires "/". */
+  if (uri->path == NULL || uri->path[0] == '\0')
+    {
+      uri->path = apr_pstrdup(result_pool, "/");
+    }
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/patch-exec/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_subr/auth.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_subr/auth.c Fri Sep 25 23:26:59 2015
@@ -370,7 +370,9 @@ svn_auth_next_credentials(void **credent
       if (creds != NULL)
         {
           /* Put the creds in the cache */
-          svn_hash_sets(auth_baton->creds_cache, state->cache_key, creds);
+          svn_hash_sets(auth_baton->creds_cache,
+                        apr_pstrdup(auth_baton->pool, state->cache_key),
+                        creds);
           break;
         }
 

Modified: subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c (original)
+++ subversion/branches/patch-exec/subversion/libsvn_subr/win32_crashrpt.c Fri Sep 25 23:26:59 2015
@@ -53,9 +53,9 @@ HANDLE dbghelp_dll = INVALID_HANDLE_VALU
 #define LOGFILE_PREFIX "svn-crash-log"
 
 #if defined(_M_IX86)
-#define FORMAT_PTR "0x%08x"
+#define FORMAT_PTR "0x%08Ix"
 #elif defined(_M_X64)
-#define FORMAT_PTR "0x%016I64x"
+#define FORMAT_PTR "0x%016Ix"
 #endif
 
 /*** Code. ***/
@@ -171,7 +171,7 @@ write_module_info_callback(void *data,
       MINIDUMP_MODULE_CALLBACK module = callback_input->Module;
 
       char *buf = convert_wbcs_to_ansi(module.FullPath);
-      fprintf(log_file, FORMAT_PTR, module.BaseOfImage);
+      fprintf(log_file, FORMAT_PTR, (INT_PTR)module.BaseOfImage);
       fprintf(log_file, "  %s", buf);
       free(buf);
 
@@ -302,7 +302,7 @@ format_basic_type(char *buf, DWORD basic
         break;
       default:
         sprintf(buf, "[unhandled type 0x%08x of length " FORMAT_PTR "]",
-                     basic_type, length);
+                     basic_type, (INT_PTR)length);
         break;
     }
 }
@@ -341,7 +341,7 @@ format_value(char *value_str, DWORD64 mo
 
               if (ptr == 0)
                 sprintf(value_str, "(%s) " FORMAT_PTR,
-                        type_name, (DWORD_PTR *)value_addr);
+                        type_name, (INT_PTR)(DWORD_PTR *)value_addr);
               else if (ptr == 1)
                 sprintf(value_str, "(%s *) " FORMAT_PTR,
                         type_name, *(DWORD_PTR *)value_addr);

Modified: subversion/branches/patch-exec/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/mod_dav_svn/version.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/patch-exec/subversion/mod_dav_svn/version.c Fri Sep 25 23:26:59 2015
@@ -152,6 +152,7 @@ get_vsn_options(apr_pool_t *p, apr_text_
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INHERITED_PROPS);
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INLINE_PROPS);
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS);
+  apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_SVNDIFF1);
   /* Mergeinfo is a special case: here we merely say that the server
    * knows how to handle mergeinfo -- whether the repository does too
    * is a separate matter.

Modified: subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/branches/patch-exec/subversion/tests/cmdline/patch_tests.py Fri Sep 25 23:26:59 2015
@@ -3647,7 +3647,7 @@ def patch_lacking_trailing_eol(sbox):
 
   # Expect a newline to be appended
   expected_disk = svntest.main.greek_state.copy()
-  expected_disk.tweak('iota', contents=iota_contents + "Some more bytes")
+  expected_disk.tweak('iota', contents=iota_contents + "Some more bytes\n")
 
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.tweak('iota', status='M ')
@@ -4559,7 +4559,6 @@ def patch_apply_no_fuz(sbox):
   if not filecmp.cmp(sbox.ospath('test.txt'), sbox.ospath('test_v2.txt')):
     raise svntest.Failure("Patch result not identical")
 
-@XFail()
 def patch_lacking_trailing_eol_on_context(sbox):
   "patch file lacking trailing eol on context"
 
@@ -5620,7 +5619,6 @@ def patch_obstructing_symlink_traversal(
                                        expected_output, expected_disk,
                                        expected_status, expected_skip)
 
-@XFail()
 def patch_binary_file(sbox):
   "patch a binary file"
 
@@ -5664,14 +5662,305 @@ def patch_binary_file(sbox):
   expected_output = wc.State(wc_dir, {
     'iota'              : Item(status='UU'),
   })
-  expected_disk = None
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota',
+                      props={'svn:mime-type':'application/binary'},
+                      contents =
+                      'This is the file \'iota\'.\n'
+                      '\0\202\203\204\205\206\207nsomething\nelse\xFF')
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.tweak('iota', status='MM')
   expected_skip = wc.State('', { })
 
   svntest.actions.run_and_verify_patch(wc_dir, tmp,
                                        expected_output, expected_disk,
-                                       expected_status, expected_skip)
+                                       expected_status, expected_skip,
+                                       [], True, True)
+
+  # Ok, now try applying it backwards
+  expected_output.tweak('iota', status='GU')
+  expected_disk = svntest.main.greek_state.copy()
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  svntest.actions.run_and_verify_patch(wc_dir, tmp,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
+
+def patch_delete_nodes(sbox):
+  "apply deletes via patch"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_propset('A', 'B', 'A/B/E/alpha')
+  sbox.simple_append('A/mu', '\0')
+  sbox.simple_propset('svn:mime-type', 'application/nonsense', 'A/mu')
+
+  sbox.simple_commit() # r2
+  sbox.simple_update()
+
+  expected_skip = wc.State('', { })
+
+  original_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  original_disk = svntest.main.greek_state.copy()
+  original_disk.tweak('A/mu',
+                      props={'svn:mime-type':'application/nonsense'},
+                      contents = 'This is the file \'mu\'.\n\0')
+  original_disk.tweak('A/B/E/alpha', props={'A':'B'})
+  svntest.actions.run_and_verify_status(wc_dir, original_status)
+  svntest.actions.verify_disk(wc_dir, original_disk, True)
+
+  sbox.simple_rm('A/B/E/alpha', 'A/B/E/beta', 'A/mu')
+
+  _, diff, _ = svntest.actions.run_and_verify_svn(None, [],
+                                                  'diff', '--git', wc_dir)
+
+  patch = sbox.get_tempname('patch')
+  svntest.main.file_write(patch, ''.join(diff))
+
+  deleted_status = original_status.copy()
+  deleted_disk = original_disk.copy()
+  deleted_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/mu')
+  deleted_status.tweak('A/B/E/alpha', 'A/B/E/beta', 'A/mu', status='D ')
+
+
+  svntest.actions.run_and_verify_status(wc_dir, deleted_status)
+  svntest.actions.verify_disk(wc_dir, deleted_disk, True)
+
+  # And now apply the patch from the clean state
+  sbox.simple_revert('A/B/E/alpha', 'A/B/E/beta', 'A/mu')
+
+  # Expect that the hint 'empty dir? -> delete dir' deletes 'E'
+  # ### A smarter diff format might change this in a future version
+  deleted_disk.remove('A/B/E')
+  deleted_status.tweak('A/B/E', status='D ')
+  expected_output = wc.State(wc_dir, {
+    'A/mu'              : Item(status='D '),
+    'A/B/E'             : Item(status='D '),
+    'A/B/E/beta'        : Item(status='D '),
+    'A/B/E/alpha'       : Item(status='D '),
+  })
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, deleted_disk,
+                                       deleted_status, expected_skip,
+                                       [], False, True)
+
+  # And let's see if we can apply the reverse version of the patch
+  expected_output = wc.State(wc_dir, {
+    'A/mu'              : Item(status='A '),
+    'A/B/E'             : Item(status='A '),
+    'A/B/E/beta'        : Item(status='A '),
+    'A/B/E/alpha'       : Item(status='A '),
+  })
+  original_status.tweak('A/mu', status='RM') # New file
+  original_status.tweak('A/B/E', status='R ') # New dir
+  original_status.tweak('A/B/E/alpha', 'A/B/E/beta',
+                        status='A ', wc_rev='-',
+                        entry_status='R ', entry_rev='2')
+
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, original_disk,
+                                       original_status, expected_skip,
+                                       [], True, True, '--reverse-diff')
+
+def patch_delete_missing_eol(sbox):
+  "apply a delete missing an eol"
+
+  sbox.build(read_only = True)
+  wc_dir = sbox.wc_dir
+
+  delete_patch = [
+    "Index: A/B/E/beta\n",
+    "===================================================================\n",
+    "--- A/B/E/beta	(revision 1)\n",
+    "+++ /dev/null\n",
+    "@@ -1 +0,0 @@\n",
+    "-This is the file 'beta'." # No final EOL
+  ]
+
+  patch = sbox.get_tempname('patch')
+  svntest.main.file_write(patch, ''.join(delete_patch))
+
+  expected_output = wc.State(wc_dir, {
+    'A/B/E/beta'        : Item(status='D '),
+  })
+  expected_skip = wc.State(wc_dir, {
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/B/E/beta', status='D ')
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.remove('A/B/E/beta')
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True)
+
+  # Try again? -> Skip... Why not some already applied notification?
+  #                       -> There is nothing to compare to
+  expected_output = wc.State(wc_dir, {
+  })
+  expected_skip = wc.State(wc_dir, {
+    'A/B/E/beta'        : Item(verb='Skipped'),
+  })
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True)
+
+  # Reverse
+  expected_output = wc.State(wc_dir, {
+    'A/B/E/beta'        : Item(status='A '),
+  })
+  expected_skip = wc.State(wc_dir, {
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_status.tweak('A/B/E/beta', status='R ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
+
+  # Try again? -> Already applied
+  expected_output = wc.State(wc_dir, {
+    'A/B/E/beta'        : Item(status='G '),
+  })
+  expected_skip = wc.State(wc_dir, {
+  })
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
+
+def patch_final_eol(sbox):
+  "patch the final eol"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  delete_patch = [
+   'Index: A/mu\n',
+   '===================================================================\n',
+   '--- A/mu\t(revision 1)\n',
+   '+++ A/mu\t(working copy)\n',
+   '@@ -1 +1 @@\n',
+   '-This is the file \'mu\'.\n',
+   '+This is the file \'mu\'.\n',
+   '\ No newline at end of file\n',
+   'Index: iota\n',
+   '===================================================================\n',
+   '--- iota\t(revision 1)\n',
+   '+++ iota\t(working copy)\n',
+   '@@ -1 +1 @@\n',
+   '-This is the file \'iota\'.\n',
+   '+This is the file \'iota\'.\n',
+   '\ No newline at end of file' # Missing EOL
+  ]
+
+  patch = sbox.get_tempname('patch')
+  # We explicitly use wb here as this is the eol type added later in the test
+  svntest.main.file_write(patch, ''.join(delete_patch), mode='wb')
+
+  expected_output = wc.State(wc_dir, {
+    'A/mu'        : Item(status='U '),
+    'iota'        : Item(status='U '),
+  })
+  expected_skip = wc.State(wc_dir, {})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('iota', 'A/mu', status='M ')
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('iota', contents="This is the file 'iota'.")
+  expected_disk.tweak('A/mu', contents="This is the file 'mu'.")
+
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True)
+
+  # And again
+  expected_output.tweak('iota', 'A/mu', status='G ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True)
+
+  # Reverse
+  expected_disk.tweak('iota', contents="This is the file 'iota'.\n")
+  expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n")
+  expected_status.tweak('iota', 'A/mu', status='  ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
+
+  # And once more
+  expected_output.tweak('iota', 'A/mu', status='U ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
+
+  # Change the unmodified form
+  sbox.simple_append('iota', 'This is the file \'iota\'.', truncate=True)
+  sbox.simple_append('A/mu', 'This is the file \'mu\'.', truncate=True)
+  sbox.simple_commit()
+  expected_status.tweak('iota', 'A/mu', wc_rev='2')
+
+  add_patch = [
+    'Index: A/mu\n',
+    '===================================================================\n',
+    '--- A/mu\t(revision 2)\n',
+    '+++ A/mu\t(working copy)\n',
+    '@@ -1 +1 @@\n',
+    '-This is the file \'mu\'.\n',
+    '\ No newline at end of file\n',
+    '+This is the file \'mu\'.\n',
+    'Index: iota\n',
+    '===================================================================\n',
+    '--- iota\t(revision 2)\n',
+    '+++ iota\t(working copy)\n',
+    '@@ -1 +1 @@\n',
+    '-This is the file \'iota\'.\n',
+    '\ No newline at end of file\n',
+    '+This is the file \'iota\'.' # Missing eol
+  ]
+
+  svntest.main.file_write(patch, ''.join(add_patch), mode='wb')
+
+  # Apply the patch
+  expected_output.tweak('iota', 'A/mu', status='U ')
+  expected_disk.tweak('iota', contents="This is the file 'iota'.\n")
+  expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n")
+  expected_status.tweak('iota', 'A/mu', status='M ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True)
+
+  # And again
+  expected_output.tweak('iota', 'A/mu', status='G ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True)
+
+  # And in reverse
+  expected_disk.tweak('iota', contents="This is the file 'iota'.")
+  expected_disk.tweak('A/mu', contents="This is the file 'mu'.")
+  expected_status.tweak('iota', 'A/mu', status='  ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
+
+  # And again
+  expected_output.tweak('iota', 'A/mu', status='U ')
+  svntest.actions.run_and_verify_patch(wc_dir, patch,
+                                       expected_output, expected_disk,
+                                       expected_status, expected_skip,
+                                       [], False, True, '--reverse-diff')
 
 def patch_adds_executability_nocontents(sbox):
   """patch adds svn:executable, without contents"""
@@ -5855,7 +6144,7 @@ def patch_ambiguous_executability_consis
                                        expected_status, expected_skip,
                                        error_re_string=None,
                                        check_props=True)
-
+ 
 ########################################################################
 #Run the tests
 
@@ -5918,6 +6207,9 @@ test_list = [ None,
               patch_symlink_traversal,
               patch_obstructing_symlink_traversal,
               patch_binary_file,
+              patch_delete_nodes,
+              patch_delete_missing_eol,
+              patch_final_eol,
               patch_adds_executability_nocontents,
               patch_adds_executability_yescontents,
               patch_deletes_executability,

Modified: subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/branches/patch-exec/subversion/tests/libsvn_diff/parse-diff-test.c Fri Sep 25 23:26:59 2015
@@ -305,6 +305,24 @@ create_patch_file(svn_patch_file_t **pat
   return SVN_NO_ERROR;
 }
 
+/* svn_stream_readline() with hunk reader semantics */
+static svn_error_t *
+stream_readline_diff(svn_stream_t *stream,
+                     svn_stringbuf_t **buf,
+                     const char *eol,
+                     svn_boolean_t *eof,
+                     apr_pool_t *result_pool)
+{
+  SVN_ERR(svn_stream_readline(stream, buf, eol, eof, result_pool));
+
+  /* Hunks are only at EOF after they are completely read, even if
+     they don't have a final EOL in the text */
+  if (*eof && (*buf)->len)
+    *eof = FALSE;
+
+  return SVN_NO_ERROR;
+}
+
 /* Check that reading a line from HUNK equals what's inside EXPECTED.
  * If ORIGINAL is TRUE, read the original hunk text; else, read the
  * modified hunk text. */
@@ -323,7 +341,7 @@ check_content(svn_diff_hunk_t *hunk, svn
 
   while (TRUE)
   {
-    SVN_ERR(svn_stream_readline(exp, &exp_buf, NL, &exp_eof, pool));
+    SVN_ERR(stream_readline_diff(exp, &exp_buf, NL, &exp_eof, pool));
     if (original)
       SVN_ERR(svn_diff_hunk_readline_original_text(hunk, &hunk_buf, NULL,
                                                    &hunk_eof, pool, pool));

Modified: subversion/branches/patch-exec/tools/dist/backport/merger.py
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/tools/dist/backport/merger.py?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/tools/dist/backport/merger.py (original)
+++ subversion/branches/patch-exec/tools/dist/backport/merger.py Fri Sep 25 23:26:59 2015
@@ -161,7 +161,7 @@ def merge(entry, expected_stderr=None, *
   # Prepare mergeargs and logmsg.
   logmsg = ""
   if entry.branch:
-    branch_url = "%s/%s" % (sf.BRANCHES, entry.branch)
+    branch_url = sf.branch_url(entry.branch)
     if svn_version() >= (1, 8):
       mergeargs = ['--', branch_url]
       logmsg = "Merge {}:\n".format(entry.noun())
@@ -181,7 +181,7 @@ def merge(entry, expected_stderr=None, *
       logmsg += "Merge {} from trunk:\n".format(entry.noun())
     logmsg += "\n"
     mergeargs.extend('-c' + str(revision) for revision in entry.revisions)
-    mergeargs.extend(['--', sf.TRUNK])
+    mergeargs.extend(['--', sf.trunk_url()])
   logmsg += entry.raw
 
   # TODO(interactive mode): exclude STATUS from reverts
@@ -237,9 +237,9 @@ def validate_branch_contains_named_revis
     return # skip check
 
   sf = entry.status_file
-  branch_url = "%s/%s" % (sf.BRANCHES, entry.branch)
+  branch_url = sf.branch_url(entry.branch)
   present_str = (
-    run_svn(['mergeinfo', '--show-revs=merged', '--', sf.TRUNK, branch_url])[1]
+    run_svn(['mergeinfo', '--show-revs=merged', '--', sf.trunk_url(), branch_url])[1]
     +
     run_svn(['mergeinfo', '--show-revs=eligible', '--', branch_url])[1]
   )

Modified: subversion/branches/patch-exec/tools/dist/backport/status.py
URL: http://svn.apache.org/viewvc/subversion/branches/patch-exec/tools/dist/backport/status.py?rev=1705385&r1=1705384&r2=1705385&view=diff
==============================================================================
--- subversion/branches/patch-exec/tools/dist/backport/status.py (original)
+++ subversion/branches/patch-exec/tools/dist/backport/status.py Fri Sep 25 23:26:59 2015
@@ -157,13 +157,24 @@ class Paragraph:
 class StatusFile:
   "Encapsulates the STATUS file."
 
-  TRUNK = '^/subversion/trunk'
-  BRANCHES = '^/subversion/branches'
-
   def __init__(self, status_fp):
     "Constructor.  STATUS_FP is an open file-like object to parse."
     self._parse(status_fp)
     self.validate_unique_entry_ids() # Use-case for making this optional?
+    self._project_root_url = '^/subversion'
+
+  def branch_url(self, branch_basename):
+    """Return the URL of a branch with a given basename, of 'Branch:' headers
+    that specify a basename only.
+
+    The returned URL may be an ^/foo short URL."""
+    return (self._project_root_url + "/branches/" + branch_basename)
+
+  def trunk_url(self):
+    """Return the URL to trunk.  Trunk is used as the default merge source.
+
+    The returned URL may be an ^/foo short URL."""
+    return self._project_root_url + '/trunk'
 
   def _parse(self, status_fp):
     "Parse self.status_fp into self.paragraphs."



Mime
View raw message