You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/10/06 10:46:44 UTC

svn commit: r1706963 [1/6] - in /subversion/branches/move-tracking-2: ./ build/ subversion/ subversion/bindings/javahl/native/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs_base/ ...

Author: julianfoad
Date: Tue Oct  6 08:46:43 2015
New Revision: 1706963

URL: http://svn.apache.org/viewvc?rev=1706963&view=rev
Log:
On the 'move-tracking-2' branch: catch up to trunk@1706962.

Modified:
    subversion/branches/move-tracking-2/   (props changed)
    subversion/branches/move-tracking-2/build/   (props changed)
    subversion/branches/move-tracking-2/build/run_tests.py
    subversion/branches/move-tracking-2/subversion/   (props changed)
    subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
    subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
    subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_StateReporter.cpp
    subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigImpl_Category.cpp
    subversion/branches/move-tracking-2/subversion/include/private/svn_diff_private.h
    subversion/branches/move-tracking-2/subversion/include/private/svn_diff_tree.h
    subversion/branches/move-tracking-2/subversion/include/private/svn_fs_fs_private.h
    subversion/branches/move-tracking-2/subversion/include/svn_diff.h
    subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c
    subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c
    subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c
    subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c
    subversion/branches/move-tracking-2/subversion/libsvn_client/upgrade.c
    subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c
    subversion/branches/move-tracking-2/subversion/libsvn_diff/parse-diff.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_base/tree.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/pack.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h
    subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/multistatus.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/config.c
    subversion/branches/move-tracking-2/subversion/libsvn_subr/opt.c
    subversion/branches/move-tracking-2/subversion/libsvn_wc/diff.h
    subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c
    subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c
    subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_pristine.c
    subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c
    subversion/branches/move-tracking-2/subversion/svn/notify.c
    subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c
    subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/patch_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/svnadmin_tests.py
    subversion/branches/move-tracking-2/subversion/tests/cmdline/svnfsfs_tests.py
    subversion/branches/move-tracking-2/subversion/tests/libsvn_client/client-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_diff/parse-diff-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c
    subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/bit-array-test.c
    subversion/branches/move-tracking-2/win-tests.py   (contents, props changed)

Propchange: subversion/branches/move-tracking-2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Oct  6 08:46:43 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:1606692-1705711
+/subversion/trunk:1606692-1706962

Propchange: subversion/branches/move-tracking-2/build/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Oct  6 08:46:43 2015
@@ -82,4 +82,4 @@
 /subversion/branches/verify-at-commit/build:1462039-1462408
 /subversion/branches/verify-keep-going/build:1439280-1546110
 /subversion/branches/wc-collate-path/build:1402685-1480384
-/subversion/trunk/build:1606692-1704317
+/subversion/trunk/build:1606692-1706962

Modified: subversion/branches/move-tracking-2/build/run_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/build/run_tests.py?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/build/run_tests.py (original)
+++ subversion/branches/move-tracking-2/build/run_tests.py Tue Oct  6 08:46:43 2015
@@ -192,7 +192,7 @@ class TestHarness:
     if self.opts.fsfs_version is not None:
       cmdline.append('--fsfs-version=%d' % self.opts.fsfs_version)
     if self.opts.server_minor_version is not None:
-      cmdline.append('--server-minor-version=' +
+      cmdline.append('--server-minor-version=%d' %
                      self.opts.server_minor_version)
     if self.opts.mode_filter is not None:
       cmdline.append('--mode-filter=' + self.opts.mode_filter)
@@ -214,7 +214,7 @@ class TestHarness:
       else:
         cmdline.append('--parallel-instances=%d' % self.opts.parallel)
     if self.opts.svn_bin is not None:
-      cmdline.append('--bin=%s', self.opts.svn_bin)
+      cmdline.append('--bin=%s' % self.opts.svn_bin)
     if self.opts.url is not None:
       cmdline.append('--url=%s' % self.opts.url)
     if self.opts.fs_type is not None:

Propchange: subversion/branches/move-tracking-2/subversion/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Oct  6 08:46:43 2015
@@ -82,4 +82,4 @@
 /subversion/branches/verify-at-commit/subversion:1462039-1462408
 /subversion/branches/verify-keep-going/subversion:1439280-1546110
 /subversion/branches/wc-collate-path/subversion:1402685-1480384
-/subversion/trunk/subversion:1606692-1705711
+/subversion/trunk/subversion:1606692-1706962

Modified: subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Tue Oct  6 08:46:43 2015
@@ -298,7 +298,7 @@ JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_SVNClient_setTunnelAgent
 (JNIEnv *env, jobject jthis, jobject jtunnelcb)
 {
-  JNIEntry(SVNClient, setPrompt);
+  JNIEntry(SVNClient, setTunnelAgent);
   SVNClient *cl = SVNClient::getCppObject(jthis);
   if (cl == NULL)
     {
@@ -1045,7 +1045,7 @@ Java_org_apache_subversion_javahl_SVNCli
  jbyteArray jval, jobject jmessage, jboolean jforce, jobject jrevpropTable,
  jobject jcallback)
 {
-  JNIEntry(SVNClient, propertySet);
+  JNIEntry(SVNClient, propertySetRemote);
   SVNClient *cl = SVNClient::getCppObject(jthis);
   if (cl == NULL)
     {
@@ -1083,7 +1083,7 @@ Java_org_apache_subversion_javahl_SVNCli
 (JNIEnv *env, jobject jthis, jobject jtargets, jstring jname,
  jbyteArray jval, jobject jdepth, jobject jchangelists, jboolean jforce)
 {
-  JNIEntry(SVNClient, propertySet);
+  JNIEntry(SVNClient, propertySetLocal);
   SVNClient *cl = SVNClient::getCppObject(jthis);
   if (cl == NULL)
     {
@@ -1968,7 +1968,7 @@ Java_org_apache_subversion_javahl_SVNCli
  jboolean jfixRecordedTimestamps, jboolean jremoveUnusedPristines,
  jboolean jincludeExternals)
 {
-  JNIEntry(SVNClient, patch);
+  JNIEntry(SVNClient, vacuum);
   SVNClient *cl = SVNClient::getCppObject(jthis);
   if (cl == NULL)
     {
@@ -1987,7 +1987,7 @@ JNIEXPORT jobject JNICALL
 Java_org_apache_subversion_javahl_SVNClient_nativeOpenRemoteSession
 (JNIEnv *env, jobject jthis, jstring jpath, jint jretryAttempts)
 {
-  JNIEntry(SVNClient, openRemoteSession);
+  JNIEntry(SVNClient, nativeOpenRemoteSession);
   SVNClient *cl = SVNClient::getCppObject(jthis);
   if (cl == NULL)
     {

Modified: subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp (original)
+++ subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_RemoteSession.cpp Tue Oct  6 08:46:43 2015
@@ -70,7 +70,7 @@ JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_remote_RemoteSession_reparent(
     JNIEnv *env, jobject jthis, jstring jurl)
 {
-  JNIEntry(RemoteSession, getSessionUrl);
+  JNIEntry(RemoteSession, reparent);
   RemoteSession *ras = RemoteSession::getCppObject(jthis);
   CPPADDR_NULL_PTR(ras, );
 
@@ -81,7 +81,7 @@ JNIEXPORT jstring JNICALL
 Java_org_apache_subversion_javahl_remote_RemoteSession_getSessionRelativePath(
     JNIEnv *env, jobject jthis, jstring jurl)
 {
-  JNIEntry(RemoteSession, getSessionUrl);
+  JNIEntry(RemoteSession, getSessionRelativePath);
   RemoteSession *ras = RemoteSession::getCppObject(jthis);
   CPPADDR_NULL_PTR(ras, NULL);
 
@@ -92,7 +92,7 @@ JNIEXPORT jstring JNICALL
 Java_org_apache_subversion_javahl_remote_RemoteSession_getReposRelativePath(
     JNIEnv *env, jobject jthis, jstring jurl)
 {
-  JNIEntry(RemoteSession, getSessionUrl);
+  JNIEntry(RemoteSession, getReposRelativePath);
   RemoteSession *ras = RemoteSession::getCppObject(jthis);
   CPPADDR_NULL_PTR(ras, NULL);
 
@@ -114,7 +114,7 @@ JNIEXPORT jstring JNICALL
 Java_org_apache_subversion_javahl_remote_RemoteSession_getReposUUID(
     JNIEnv *env, jobject jthis)
 {
-  JNIEntry(RemoteSession, geRepostUUID);
+  JNIEntry(RemoteSession, getReposUUID);
   RemoteSession *ras = RemoteSession::getCppObject(jthis);
   CPPADDR_NULL_PTR(ras, NULL);
 
@@ -125,7 +125,7 @@ JNIEXPORT jstring JNICALL
 Java_org_apache_subversion_javahl_remote_RemoteSession_getReposRootUrl(
     JNIEnv *env, jobject jthis)
 {
-  JNIEntry(RemoteSession, geRepostUUID);
+  JNIEntry(RemoteSession, getReposRootUrl);
   RemoteSession *ras = RemoteSession::getCppObject(jthis);
   CPPADDR_NULL_PTR(ras, NULL);
 
@@ -147,7 +147,7 @@ JNIEXPORT jlong JNICALL
 Java_org_apache_subversion_javahl_remote_RemoteSession_getRevisionByTimestamp(
     JNIEnv *env, jobject jthis, jlong timestamp)
 {
-  JNIEntry(RemoteSession, getDatedRevision);
+  JNIEntry(RemoteSession, getRevisionByTimestamp);
   RemoteSession *ras = RemoteSession::getCppObject(jthis);
   CPPADDR_NULL_PTR(ras, SVN_INVALID_REVNUM);
 

Modified: subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_StateReporter.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_StateReporter.cpp?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_StateReporter.cpp (original)
+++ subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_remote_StateReporter.cpp Tue Oct  6 08:46:43 2015
@@ -47,7 +47,7 @@ JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_remote_StateReporter_nativeDispose(
     JNIEnv* env, jobject jthis)
 {
-  JNIEntry(StateReporter, nativeCreateInstance);
+  JNIEntry(StateReporter, nativeDispose);
   StateReporter* reporter = StateReporter::getCppObject(jthis);
   CPPADDR_NULL_PTR(reporter,);
   reporter->dispose(jthis);

Modified: subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigImpl_Category.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigImpl_Category.cpp?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigImpl_Category.cpp (original)
+++ subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigImpl_Category.cpp Tue Oct  6 08:46:43 2015
@@ -260,7 +260,7 @@ Java_org_apache_subversion_javahl_util_C
     JNIEnv* env, jobject jthis, jstring jcategory, jlong jcontext,
     jstring jsection, jobject jhandler)
 {
-  JNIEntry(ConfigImpl$Category, sections);
+  JNIEntry(ConfigImpl$Category, enumerate);
   const ImplContext ctx(env, jthis, jcategory, jcontext, jsection, NULL);
 
   struct enumerator_t

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_diff_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_diff_private.h?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_diff_private.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_diff_private.h Tue Oct  6 08:46:43 2015
@@ -123,7 +123,7 @@ svn_diff__display_prop_diffs(svn_stream_
 svn_error_t *
 svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk,
                                        const char *line,
-                                       svn_patch_t *patch,
+                                       const svn_patch_t *patch,
                                        apr_pool_t *result_pool,
                                        apr_pool_t *scratch_pool);
 
@@ -137,7 +137,7 @@ svn_diff_hunk__create_adds_single_line(s
 svn_error_t *
 svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk,
                                           const char *line,
-                                          svn_patch_t *patch,
+                                          const svn_patch_t *patch,
                                           apr_pool_t *result_pool,
                                           apr_pool_t *scratch_pool);
 

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_diff_tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_diff_tree.h?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_diff_tree.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_diff_tree.h Tue Oct  6 08:46:43 2015
@@ -114,12 +114,24 @@ extern "C" {
  * ### How come many users don't set the 'repos_relpath' field? */
 typedef struct svn_diff_source_t
 {
-  /* Always available */
+  /* Always available
+     In case of copyfrom: the revision copied from
+   */
   svn_revnum_t revision;
 
-  /* Depending on the driver available for copyfrom */
-  /* ### What? */
+  /* In case of copyfrom: the repository relative path copied from.
+
+     NULL if the node wasn't copied or moved, or when the driver doesn't
+     have this information */
   const char *repos_relpath;
+
+  /* In case of copyfrom: the relative path of source location before the
+     move. This path is relative WITHIN THE DIFF. The repository path is
+     typically in repos_relpath
+
+     NULL if the node wasn't moved or if the driver doesn't have this
+     information. */
+  const char *moved_from_relpath;
 } svn_diff_source_t;
 
 /**

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_fs_fs_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_fs_fs_private.h?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_fs_fs_private.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_fs_fs_private.h Tue Oct  6 08:46:43 2015
@@ -152,6 +152,9 @@ typedef struct svn_fs_fs__representation
   /* sum of ref_count * expanded_size,
    * i.e. total plaintext content if there was no rep sharing */
   apr_uint64_t expanded_size;
+
+  /* sum of all representation delta chain lengths */
+  apr_uint64_t chain_len;
 } svn_fs_fs__representation_stats_t;
 
 /* Basic statistics we collect over a given set of noderevs.

Modified: subversion/branches/move-tracking-2/subversion/include/svn_diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_diff.h?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_diff.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_diff.h Tue Oct  6 08:46:43 2015
@@ -1289,23 +1289,38 @@ typedef struct svn_patch_t {
    * @since New in 1.10. */
   svn_diff_binary_patch_t *binary_patch;
 
-  /** The old and new executability bits, as retrieved from the patch file.
+  /** The old and new executability bits, as retrieved from the patch file, from
+   * the git-like mode headers.
    *
-   * A patch may specify an executability change via @a old_executable_p and
-   * / @a new_executable_p, via a #SVN_PROP_EXECUTABLE propchange hunk, or both
-   * ways; however, if both ways are used, they must specify the same semantic
-   * change.
+   * A patch may specify an executability change via @a old_executable_bit and
+   * @a new_executable_bit, via a #SVN_PROP_EXECUTABLE propchange hunk, or both
+   * ways. It is upto caller how to decide how conflicting information is
+   * handled.
    *
    * #svn_tristate_unknown indicates the patch does not specify the
    * corresponding bit.
    *
    * @since New in 1.10.
    */
-  /* ### This is currently not parsed out of "index" lines (where it
-   * ### serves as an assertion of the executability state, without
-   * ### changing it).  */
-  svn_tristate_t old_executable_p; 
-  svn_tristate_t new_executable_p; 
+  svn_tristate_t old_executable_bit;
+  svn_tristate_t new_executable_bit;
+
+  /** The old and new symlink bits, as retrieved from the patch file, from
+  * the git-like mode headers.
+  *
+  * A patch may specify a symlink change via @a old_symlink_bit and
+  * @a new_symlink_bit, via a #SVN_PROP_SPECIAL propchange hunk, or both
+  * ways. It is upto caller how to decide how conflicting information is
+  * handled. Most implementations will currently just describe a replacement
+  * of the file though.
+  *
+  * #svn_tristate_unknown indicates the patch does not specify the
+  * corresponding bit.
+  *
+  * @since New in 1.10.
+  */
+  svn_tristate_t old_symlink_bit;
+  svn_tristate_t new_symlink_bit;
 } svn_patch_t;
 
 /** An opaque type representing an open patch file.

Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c Tue Oct  6 08:46:43 2015
@@ -230,113 +230,158 @@ adjust_paths_for_diff_labels(const char
 /* Generate a label for the diff output for file PATH at revision REVNUM.
    If REVNUM is invalid then it is assumed to be the current working
    copy.  Assumes the paths are already in the desired style (local
-   vs internal).  Allocate the label in POOL. */
+   vs internal).  Allocate the label in RESULT-POOL. */
 static const char *
 diff_label(const char *path,
            svn_revnum_t revnum,
-           apr_pool_t *pool)
+           apr_pool_t *result_pool)
 {
   const char *label;
   if (revnum >= 0)
-    label = apr_psprintf(pool, _("%s\t(revision %ld)"), path, revnum);
+    label = apr_psprintf(result_pool, _("%s\t(revision %ld)"), path, revnum);
   else if (revnum == DIFF_REVNUM_NONEXISTENT)
-    label = apr_psprintf(pool, _("%s\t(nonexistent)"), path);
+    label = apr_psprintf(result_pool, _("%s\t(nonexistent)"), path);
   else /* SVN_INVALID_REVNUM */
-    label = apr_psprintf(pool, _("%s\t(working copy)"), path);
+    label = apr_psprintf(result_pool, _("%s\t(working copy)"), path);
 
   return label;
 }
 
+/* Standard modes produced in git style diffs */
+static const int exec_mode =                 0755;
+static const int noexec_mode =               0644;
+static const int kind_file_mode =         0100000;
+/*static const kind_dir_mode =            0040000;*/
+static const int kind_symlink_mode =      0120000;
+
 /* Print a git diff header for an addition within a diff between PATH1 and
- * PATH2 to the stream OS using HEADER_ENCODING.
- * All allocations are done in RESULT_POOL. */
+ * PATH2 to the stream OS using HEADER_ENCODING. */
 static svn_error_t *
 print_git_diff_header_added(svn_stream_t *os, const char *header_encoding,
                             const char *path1, const char *path2,
-                            apr_pool_t *result_pool)
+                            svn_boolean_t exec_bit,
+                            svn_boolean_t symlink_bit,
+                            apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  int new_mode = (exec_bit ? exec_mode : noexec_mode)
+                 | (symlink_bit ? kind_symlink_mode : kind_file_mode);
+
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "diff --git a/%s b/%s%s",
                                       path1, path2, APR_EOL_STR));
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
-                                      "new file mode 100644" APR_EOL_STR));
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
+                                      "new file mode %06o" APR_EOL_STR,
+                                      new_mode));
   return SVN_NO_ERROR;
 }
 
 /* Print a git diff header for a deletion within a diff between PATH1 and
- * PATH2 to the stream OS using HEADER_ENCODING.
- * All allocations are done in RESULT_POOL. */
+ * PATH2 to the stream OS using HEADER_ENCODING. */
 static svn_error_t *
 print_git_diff_header_deleted(svn_stream_t *os, const char *header_encoding,
                               const char *path1, const char *path2,
-                              apr_pool_t *result_pool)
+                              svn_boolean_t exec_bit,
+                              svn_boolean_t symlink_bit,
+                              apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  int old_mode = (exec_bit ? exec_mode : noexec_mode)
+                 | (symlink_bit ? kind_symlink_mode : kind_file_mode);
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "diff --git a/%s b/%s%s",
                                       path1, path2, APR_EOL_STR));
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
-                                      "deleted file mode 100644"
-                                      APR_EOL_STR));
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
+                                      "deleted file mode %06o" APR_EOL_STR,
+                                      old_mode));
   return SVN_NO_ERROR;
 }
 
 /* Print a git diff header for a copy from COPYFROM_PATH to PATH to the stream
- * OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */
+ * OS using HEADER_ENCODING. */
 static svn_error_t *
 print_git_diff_header_copied(svn_stream_t *os, const char *header_encoding,
                              const char *copyfrom_path,
                              svn_revnum_t copyfrom_rev,
                              const char *path,
-                             apr_pool_t *result_pool)
+                             apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "diff --git a/%s b/%s%s",
                                       copyfrom_path, path, APR_EOL_STR));
   if (copyfrom_rev != SVN_INVALID_REVNUM)
-    SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+    SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                         "copy from %s@%ld%s", copyfrom_path,
                                         copyfrom_rev, APR_EOL_STR));
   else
-    SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+    SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                         "copy from %s%s", copyfrom_path,
                                         APR_EOL_STR));
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "copy to %s%s", path, APR_EOL_STR));
   return SVN_NO_ERROR;
 }
 
 /* Print a git diff header for a rename from COPYFROM_PATH to PATH to the
- * stream OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */
+ * stream OS using HEADER_ENCODING. */
 static svn_error_t *
 print_git_diff_header_renamed(svn_stream_t *os, const char *header_encoding,
                               const char *copyfrom_path, const char *path,
-                              apr_pool_t *result_pool)
+                              apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "diff --git a/%s b/%s%s",
                                       copyfrom_path, path, APR_EOL_STR));
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "rename from %s%s", copyfrom_path,
                                       APR_EOL_STR));
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "rename to %s%s", path, APR_EOL_STR));
   return SVN_NO_ERROR;
 }
 
 /* Print a git diff header for a modification within a diff between PATH1 and
- * PATH2 to the stream OS using HEADER_ENCODING.
- * All allocations are done in RESULT_POOL. */
+ * PATH2 to the stream OS using HEADER_ENCODING. */
 static svn_error_t *
 print_git_diff_header_modified(svn_stream_t *os, const char *header_encoding,
                                const char *path1, const char *path2,
-                               apr_pool_t *result_pool)
+                               apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
                                       "diff --git a/%s b/%s%s",
                                       path1, path2, APR_EOL_STR));
   return SVN_NO_ERROR;
 }
 
+/* Helper function for print_git_diff_header */
+static svn_error_t *
+maybe_print_mode_change(svn_stream_t *os,
+                        const char *header_encoding,
+                        svn_boolean_t exec_bit1,
+                        svn_boolean_t exec_bit2,
+                        svn_boolean_t symlink_bit1,
+                        svn_boolean_t symlink_bit2,
+                        const char *git_index_shas,
+                        apr_pool_t *scratch_pool)
+{
+  int old_mode = (exec_bit1 ? exec_mode : noexec_mode)
+                 | (symlink_bit1 ? kind_symlink_mode : kind_file_mode);
+  int new_mode = (exec_bit2 ? exec_mode : noexec_mode)
+                 | (symlink_bit2 ? kind_symlink_mode : kind_file_mode);
+  if (old_mode == new_mode)
+    {
+      if (git_index_shas)
+        SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
+                                            "index %s %06o" APR_EOL_STR,
+                                            git_index_shas, old_mode));
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
+                                      "old mode %06o" APR_EOL_STR, old_mode));
+  SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
+                                      "new mode %06o" APR_EOL_STR, new_mode));
+  return SVN_NO_ERROR;
+}
+
 /* Print a git diff header showing the OPERATION to the stream OS using
  * HEADER_ENCODING. Return suitable diff labels for the git diff in *LABEL1
  * and *LABEL2. REPOS_RELPATH1 and REPOS_RELPATH2 are relative to reposroot.
@@ -354,13 +399,26 @@ print_git_diff_header(svn_stream_t *os,
                       svn_revnum_t rev2,
                       const char *copyfrom_path,
                       svn_revnum_t copyfrom_rev,
+                      apr_hash_t *left_props,
+                      apr_hash_t *right_props,
+                      const char *git_index_shas,
                       const char *header_encoding,
                       apr_pool_t *scratch_pool)
 {
+  svn_boolean_t exec_bit1 = (svn_prop_get_value(left_props,
+                                                SVN_PROP_EXECUTABLE) != NULL);
+  svn_boolean_t exec_bit2 = (svn_prop_get_value(right_props,
+                                                SVN_PROP_EXECUTABLE) != NULL);
+  svn_boolean_t symlink_bit1 = (svn_prop_get_value(left_props,
+                                                   SVN_PROP_SPECIAL) != NULL);
+  svn_boolean_t symlink_bit2 = (svn_prop_get_value(right_props,
+                                                   SVN_PROP_SPECIAL) != NULL);
+
   if (operation == svn_diff_op_deleted)
     {
       SVN_ERR(print_git_diff_header_deleted(os, header_encoding,
                                             repos_relpath1, repos_relpath2,
+                                            exec_bit1, symlink_bit1,
                                             scratch_pool));
       *label1 = diff_label(apr_psprintf(scratch_pool, "a/%s", repos_relpath1),
                            rev1, scratch_pool);
@@ -377,11 +435,17 @@ print_git_diff_header(svn_stream_t *os,
                            rev1, scratch_pool);
       *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
                            rev2, scratch_pool);
+      SVN_ERR(maybe_print_mode_change(os, header_encoding,
+                                      exec_bit1, exec_bit2,
+                                      symlink_bit1, symlink_bit2,
+                                      git_index_shas,
+                                      scratch_pool));
     }
   else if (operation == svn_diff_op_added)
     {
       SVN_ERR(print_git_diff_header_added(os, header_encoding,
                                           repos_relpath1, repos_relpath2,
+                                          exec_bit2, symlink_bit2,
                                           scratch_pool));
       *label1 = diff_label("/dev/null", rev1, scratch_pool);
       *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
@@ -396,6 +460,11 @@ print_git_diff_header(svn_stream_t *os,
                            rev1, scratch_pool);
       *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
                            rev2, scratch_pool);
+      SVN_ERR(maybe_print_mode_change(os, header_encoding,
+                                      exec_bit1, exec_bit2,
+                                      symlink_bit1, symlink_bit2,
+                                      git_index_shas,
+                                      scratch_pool));
     }
   else if (operation == svn_diff_op_moved)
     {
@@ -406,6 +475,11 @@ print_git_diff_header(svn_stream_t *os,
                            rev1, scratch_pool);
       *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
                            rev2, scratch_pool);
+      SVN_ERR(maybe_print_mode_change(os, header_encoding,
+                                      exec_bit1, exec_bit2,
+                                      symlink_bit1, symlink_bit2,
+                                      git_index_shas,
+                                      scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -425,7 +499,8 @@ print_git_diff_header(svn_stream_t *os,
    ANCHOR is the local path where the diff editor is anchored. */
 static svn_error_t *
 display_prop_diffs(const apr_array_header_t *propchanges,
-                   apr_hash_t *original_props,
+                   apr_hash_t *left_props,
+                   apr_hash_t *right_props,
                    const char *diff_relpath,
                    const char *anchor,
                    const char *orig_path1,
@@ -487,6 +562,9 @@ display_prop_diffs(const apr_array_heade
                                       repos_relpath1, repos_relpath2,
                                       rev1, rev2, NULL,
                                       SVN_INVALID_REVNUM,
+                                      left_props,
+                                      right_props,
+                                      NULL,
                                       encoding, scratch_pool));
 
       /* --- label1
@@ -507,7 +585,7 @@ display_prop_diffs(const apr_array_heade
                                       SVN_DIFF__UNDER_STRING APR_EOL_STR));
 
   SVN_ERR(svn_diff__display_prop_diffs(
-            outstream, encoding, propchanges, original_props,
+            outstream, encoding, propchanges, left_props,
             TRUE /* pretty_print_mergeinfo */,
             -1 /* context_size */,
             cancel_func, cancel_baton, scratch_pool));
@@ -606,7 +684,8 @@ diff_props_changed(const char *diff_relp
                    svn_revnum_t rev1,
                    svn_revnum_t rev2,
                    const apr_array_header_t *propchanges,
-                   apr_hash_t *original_props,
+                   apr_hash_t *left_props,
+                   apr_hash_t *right_props,
                    svn_boolean_t show_diff_header,
                    diff_writer_info_t *dwi,
                    apr_pool_t *scratch_pool)
@@ -625,7 +704,7 @@ diff_props_changed(const char *diff_relp
       /* We're using the revnums from the dwi since there's
        * no revision argument to the svn_wc_diff_callback_t
        * dir_props_changed(). */
-      SVN_ERR(display_prop_diffs(props, original_props,
+      SVN_ERR(display_prop_diffs(props, left_props, right_props,
                                  diff_relpath,
                                  dwi->ddi.anchor,
                                  dwi->ddi.orig_path_1,
@@ -647,6 +726,61 @@ diff_props_changed(const char *diff_relp
   return SVN_NO_ERROR;
 }
 
+/* Given a file TMPFILE, return a path to a temporary file that lives at least
+   as long as RESULT_POOL, containing the git-like represention of TMPFILE */
+static svn_error_t *
+transform_link_to_git(const char **new_tmpfile,
+                      const char **git_sha1,
+                      const char *tmpfile,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  apr_file_t *orig;
+  apr_file_t *gitlike;
+  svn_stringbuf_t *line;
+
+  *git_sha1 = NULL;
+
+  SVN_ERR(svn_io_file_open(&orig, tmpfile, APR_READ, APR_OS_DEFAULT,
+                           scratch_pool));
+  SVN_ERR(svn_io_open_unique_file3(&gitlike, new_tmpfile, NULL,
+                                   svn_io_file_del_on_pool_cleanup,
+                                   result_pool, scratch_pool));
+
+  SVN_ERR(svn_io_file_readline(orig, &line, NULL, NULL, 2 * APR_PATH_MAX + 2,
+                               scratch_pool, scratch_pool));
+
+  if (line->len > 5 && !strncmp(line->data, "link ", 5))
+    {
+      const char *sz_str;
+      svn_checksum_t *checksum;
+
+      svn_stringbuf_remove(line, 0, 5);
+
+      SVN_ERR(svn_io_file_write_full(gitlike, line->data, line->len,
+                                     NULL, scratch_pool));
+
+      /* git calculates the sha over "blob X\0" + the actual data,
+         where X is the decimal size of the blob. */
+      sz_str = apr_psprintf(scratch_pool, "blob %u", (unsigned int)line->len);
+      svn_stringbuf_insert(line, 0, sz_str, strlen(sz_str) + 1);
+
+      SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
+                           line->data, line->len, scratch_pool));
+
+      *git_sha1 = svn_checksum_to_cstring(checksum, result_pool);
+    }
+  else
+    {
+      /* Not a link... so can't convert */
+      *new_tmpfile = apr_pstrdup(result_pool, tmpfile);
+    }
+
+  SVN_ERR(svn_io_file_close(orig, scratch_pool));
+  SVN_ERR(svn_io_file_close(gitlike, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
 /* Show differences between TMPFILE1 and TMPFILE2. DIFF_RELPATH, REV1, and
    REV2 are used in the headers to indicate the file and revisions.  If either
    MIMETYPE1 or MIMETYPE2 indicate binary content, don't show a diff,
@@ -662,8 +796,8 @@ diff_content_changed(svn_boolean_t *wrot
                      const char *tmpfile2,
                      svn_revnum_t rev1,
                      svn_revnum_t rev2,
-                     const char *mimetype1,
-                     const char *mimetype2,
+                     apr_hash_t *left_props,
+                     apr_hash_t *right_props,
                      svn_diff_operation_kind_t operation,
                      svn_boolean_t force_diff,
                      const char *copyfrom_path,
@@ -678,6 +812,9 @@ diff_content_changed(svn_boolean_t *wrot
   const char *index_path = diff_relpath;
   const char *path1 = dwi->ddi.orig_path_1;
   const char *path2 = dwi->ddi.orig_path_2;
+  const char *mimetype1 = svn_prop_get_value(left_props, SVN_PROP_MIME_TYPE);
+  const char *mimetype2 = svn_prop_get_value(right_props, SVN_PROP_MIME_TYPE);
+  const char *index_shas = NULL;
 
   /* If only property differences are shown, there's nothing to do. */
   if (dwi->properties_only)
@@ -699,6 +836,33 @@ diff_content_changed(svn_boolean_t *wrot
   if (mimetype2)
     mt2_binary = svn_mime_type_is_binary(mimetype2);
 
+  if (dwi->use_git_diff_format)
+    {
+      const char *l_hash = NULL;
+      const char *r_hash = NULL;
+
+      /* Change symlinks to their 'git like' plain format */
+      if (svn_prop_get_value(left_props, SVN_PROP_SPECIAL))
+        SVN_ERR(transform_link_to_git(&tmpfile1, &l_hash, tmpfile1,
+                                      scratch_pool, scratch_pool));
+      if (svn_prop_get_value(right_props, SVN_PROP_SPECIAL))
+        SVN_ERR(transform_link_to_git(&tmpfile2, &r_hash, tmpfile2,
+                                      scratch_pool, scratch_pool));
+
+      if (l_hash && r_hash)
+        {
+          /* The symlink has changed. But we can't tell the user of the
+             diff whether we are writing git diffs or svn diffs of the
+             symlink... except when we add a git-like index line */
+
+          l_hash = apr_pstrndup(scratch_pool, l_hash, 8);
+          r_hash = apr_pstrndup(scratch_pool, r_hash, 8);
+
+          index_shas = apr_psprintf(scratch_pool, "%8s..%8s",
+                                    l_hash, r_hash);
+        }
+    }
+
   if (! dwi->force_binary && (mt1_binary || mt2_binary))
     {
       /* Print out the diff header. */
@@ -737,6 +901,9 @@ diff_content_changed(svn_boolean_t *wrot
                                         rev1, rev2,
                                         copyfrom_path,
                                         copyfrom_rev,
+                                        left_props,
+                                        right_props,
+                                        index_shas,
                                         dwi->header_encoding,
                                         scratch_pool));
 
@@ -898,6 +1065,9 @@ diff_content_changed(svn_boolean_t *wrot
                                             rev1, rev2,
                                             copyfrom_path,
                                             copyfrom_rev,
+                                            left_props,
+                                            right_props,
+                                            index_shas,
                                             dwi->header_encoding,
                                             scratch_pool));
             }
@@ -918,10 +1088,6 @@ diff_content_changed(svn_boolean_t *wrot
         }
     }
 
-  /* ### todo: someday we'll need to worry about whether we're going
-     to need to write a diff plug-in mechanism that makes use of the
-     two paths, instead of just blindly running SVN_CLIENT_DIFF.  */
-
   return SVN_NO_ERROR;
 }
 
@@ -948,10 +1114,7 @@ diff_file_changed(const char *relpath,
                                  left_file, right_file,
                                  left_source->revision,
                                  right_source->revision,
-                                 svn_prop_get_value(left_props,
-                                                    SVN_PROP_MIME_TYPE),
-                                 svn_prop_get_value(right_props,
-                                                    SVN_PROP_MIME_TYPE),
+                                 left_props, right_props,
                                  svn_diff_op_modified, FALSE,
                                  NULL,
                                  SVN_INVALID_REVNUM, dwi,
@@ -960,7 +1123,7 @@ diff_file_changed(const char *relpath,
     SVN_ERR(diff_props_changed(relpath,
                                left_source->revision,
                                right_source->revision, prop_changes,
-                               left_props, !wrote_header,
+                               left_props, right_props, !wrote_header,
                                dwi, scratch_pool));
   return SVN_NO_ERROR;
 }
@@ -1033,13 +1196,14 @@ diff_file_added(const char *relpath,
                                  left_file, right_file,
                                  copyfrom_source->revision,
                                  right_source->revision,
-                                 svn_prop_get_value(left_props,
-                                                    SVN_PROP_MIME_TYPE),
-                                 svn_prop_get_value(right_props,
-                                                    SVN_PROP_MIME_TYPE),
-                                 svn_diff_op_copied,
+                                 left_props, right_props,
+                                 copyfrom_source->moved_from_relpath
+                                    ? svn_diff_op_moved
+                                    : svn_diff_op_copied,
                                  TRUE /* force diff output */,
-                                 copyfrom_source->repos_relpath,
+                                 copyfrom_source->moved_from_relpath
+                                    ? copyfrom_source->moved_from_relpath
+                                    : copyfrom_source->repos_relpath,
                                  copyfrom_source->revision,
                                  dwi, scratch_pool));
   else if (right_file)
@@ -1047,10 +1211,7 @@ diff_file_added(const char *relpath,
                                  left_file, right_file,
                                  DIFF_REVNUM_NONEXISTENT,
                                  right_source->revision,
-                                 svn_prop_get_value(left_props,
-                                                    SVN_PROP_MIME_TYPE),
-                                 svn_prop_get_value(right_props,
-                                                    SVN_PROP_MIME_TYPE),
+                                 left_props, right_props,
                                  svn_diff_op_added,
                                  TRUE /* force diff output */,
                                  NULL, SVN_INVALID_REVNUM,
@@ -1062,8 +1223,8 @@ diff_file_added(const char *relpath,
                                                : DIFF_REVNUM_NONEXISTENT,
                                right_source->revision,
                                prop_changes,
-                               left_props, ! wrote_header,
-                               dwi, scratch_pool));
+                               left_props, right_props,
+                               ! wrote_header, dwi, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1108,8 +1269,7 @@ diff_file_deleted(const char *relpath,
                                      left_file, dwi->empty_file,
                                      left_source->revision,
                                      DIFF_REVNUM_NONEXISTENT,
-                                     svn_prop_get_value(left_props,
-                                                        SVN_PROP_MIME_TYPE),
+                                     left_props,
                                      NULL,
                                      svn_diff_op_deleted, FALSE,
                                      NULL, SVN_INVALID_REVNUM,
@@ -1127,8 +1287,8 @@ diff_file_deleted(const char *relpath,
                                      left_source->revision,
                                      DIFF_REVNUM_NONEXISTENT,
                                      prop_changes,
-                                     left_props, ! wrote_header,
-                                     dwi, scratch_pool));
+                                     left_props, NULL,
+                                     ! wrote_header, dwi, scratch_pool));
         }
     }
 
@@ -1153,7 +1313,7 @@ diff_dir_changed(const char *relpath,
                              left_source->revision,
                              right_source->revision,
                              prop_changes,
-                             left_props,
+                             left_props, right_props,
                              TRUE /* show_diff_header */,
                              dwi,
                              scratch_pool));
@@ -1198,7 +1358,7 @@ diff_dir_added(const char *relpath,
                                                             : DIFF_REVNUM_NONEXISTENT,
                                             right_source->revision,
                                             prop_changes,
-                                            left_props,
+                                            left_props, right_props,
                                             TRUE /* show_diff_header */,
                                             dwi,
                                             scratch_pool));
@@ -1215,19 +1375,20 @@ diff_dir_deleted(const char *relpath,
 {
   diff_writer_info_t *dwi = processor->baton;
   apr_array_header_t *prop_changes;
+  apr_hash_t *right_props;
 
   if (dwi->no_diff_deleted)
     return SVN_NO_ERROR;
 
-
-  SVN_ERR(svn_prop_diffs(&prop_changes, apr_hash_make(scratch_pool),
+  right_props = apr_hash_make(scratch_pool);
+  SVN_ERR(svn_prop_diffs(&prop_changes, right_props,
                          left_props, scratch_pool));
 
   SVN_ERR(diff_props_changed(relpath,
                              left_source->revision,
                              DIFF_REVNUM_NONEXISTENT,
                              prop_changes,
-                             left_props,
+                             left_props, right_props,
                              TRUE /* show_diff_header */,
                              dwi,
                              scratch_pool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/externals.c Tue Oct  6 08:46:43 2015
@@ -231,6 +231,40 @@ switch_dir_external(const char *local_ab
 
       if (node_url)
         {
+          svn_boolean_t is_wcroot;
+
+          SVN_ERR(svn_wc__is_wcroot(&is_wcroot, ctx->wc_ctx, local_abspath,
+                                    pool));
+
+          if (! is_wcroot)
+          {
+            /* This can't be a directory external! */
+
+            err = svn_wc__external_remove(ctx->wc_ctx, defining_abspath,
+                                          local_abspath,
+                                          TRUE /* declaration_only */,
+                                          ctx->cancel_func, ctx->cancel_baton,
+                                          pool);
+
+            if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+              {
+                /* New external... No problem that we can't remove it */
+                svn_error_clear(err);
+                err = NULL;
+              }
+
+            return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, err,
+                                     _("The external '%s' defined in %s at '%s' "
+                                       "cannot be checked out because '%s' is "
+                                       "already a versioned path."),
+                                     url_from_externals_definition,
+                                     SVN_PROP_EXTERNALS,
+                                     svn_dirent_local_style(defining_abspath,
+                                                            pool),
+                                     svn_dirent_local_style(local_abspath,
+                                                            pool));
+          }
+
           /* If we have what appears to be a version controlled
              subdir, and its top-level URL matches that of our
              externals definition, perform an update. */

Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c Tue Oct  6 08:46:43 2015
@@ -6465,10 +6465,7 @@ get_mergeinfo_paths(apr_array_header_t *
       /* Sort CHILDREN_WITH_MERGEINFO by each child's path (i.e. as per
          compare_merge_path_t_as_paths).  Any subsequent insertions of new
          children with insert_child_to_merge() require this ordering. */
-      qsort(children_with_mergeinfo->elts,
-            children_with_mergeinfo->nelts,
-            children_with_mergeinfo->elt_size,
-            compare_merge_path_t_as_paths);
+      svn_sort__array(children_with_mergeinfo, compare_merge_path_t_as_paths);
     }
 
   /* Case 2: Switched subtrees
@@ -7077,8 +7074,7 @@ combine_range_with_segments(apr_array_he
   /* If this was a subtractive merge, and we created more than one
      merge source, we need to reverse the sort ordering of our sources. */
   if (subtractive && (merge_source_ts->nelts > 1))
-    qsort(merge_source_ts->elts, merge_source_ts->nelts,
-          merge_source_ts->elt_size, compare_merge_source_ts);
+    svn_sort__array(merge_source_ts, compare_merge_source_ts);
 
   *merge_source_ts_p = merge_source_ts;
   return SVN_NO_ERROR;