subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1428366 [1/3] - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/diff.c libsvn_client/diff_local.c svn/diff-cmd.c
Date Thu, 03 Jan 2013 14:41:13 GMT
Author: rhuijben
Date: Thu Jan  3 14:41:13 2013
New Revision: 1428366

URL: http://svn.apache.org/viewvc?rev=1428366&view=rev
Log:
Make the new in 1.8 arbritary node diff just another driver of the diff
callback api instead of using internal diff apis to produce some nice output.

This allows reusing this walker for features like the --summarize support.

* subversion/include/private/svn_client_private.h
  (svn_client__arbitrary_nodes_diff): New function.

* subversion/libsvn_client/diff.c
  (get_props,
   do_arbitrary_files_diff,
   arbitrary_diff_walker_baton,
   arbitrary_diff_walker,
   do_arbitrary_dirs_diff,
   arbitrary_diff_walker,
   do_arbitrary_nodes_diff): Move to diff_local.c

  (diff_wc_wc): Remove the arbritrary diff detection from here to ...
  (do_diff): ... its caller, here. Trigger behavior from working-working
    revision instead of overloading base-working diff in diff_wc_wc.

    Reinstate the check for unsupported specific revisions from <= 1.7
    in diff_wc_wc, instead of always running the arbritrary diff.

* subversion/libsvn_client/diff_local.c
  New file, based on diff.c
  (do_arbitrary_files_diff): Remove ignore properties and force binary code.
    This is handled by the diff callbacks.

* subversion/svn/diff-cmd.c
  (svn_cl__diff): Request working working diff.

Added:
    subversion/trunk/subversion/libsvn_client/diff_local.c
      - copied, changed from r1428337, subversion/trunk/subversion/libsvn_client/diff.c
Modified:
    subversion/trunk/subversion/include/private/svn_client_private.h
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/svn/diff-cmd.c

Modified: subversion/trunk/subversion/include/private/svn_client_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1428366&r1=1428365&r2=1428366&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Thu Jan  3 14:41:13 2013
@@ -226,6 +226,19 @@ svn_client__wc_node_get_origin(svn_clien
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
+/* Produce a diff between two files or two directories at LOCAL_ABSPATH1
+ * and LOCAL_ABSPATH2, using the provided diff callbacks to show changes
+ * in files. The files and directories involved may be part of a working
+ * copy or they may be unversioned. For versioned files, show property
+ * changes, too. */
+svn_error_t *
+svn_client__arbitrary_nodes_diff(const char *local_abspath1,
+                                 const char *local_abspath2,
+                                 const svn_wc_diff_callbacks4_t *callbacks,
+                                 void *callback_baton,
+                                 svn_client_ctx_t *ctx,
+                                 apr_pool_t *scratch_pool);
+
 
 #ifdef __cplusplus
 }

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1428366&r1=1428365&r2=1428366&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Thu Jan  3 14:41:13 2013
@@ -1563,481 +1563,6 @@ unsupported_diff_error(svn_error_t *chil
                             "that is not yet supported"));
 }
 
-/* Try to get properties for LOCAL_ABSPATH and return them in the property
- * hash *PROPS. If there are no properties because LOCAL_ABSPATH is not
- * versioned, return an empty property hash. */
-static svn_error_t *
-get_props(apr_hash_t **props,
-          const char *local_abspath,
-          svn_wc_context_t *wc_ctx,
-          apr_pool_t *result_pool,
-          apr_pool_t *scratch_pool)
-{
-  svn_error_t *err;
-
-  err = svn_wc_prop_list2(props, wc_ctx, local_abspath, result_pool,
-                          scratch_pool);
-  if (err)
-    {
-      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
-          err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY ||
-          err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
-        {
-          svn_error_clear(err);
-          *props = apr_hash_make(result_pool);
-        }
-      else
-        return svn_error_trace(err);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Produce a diff between two arbitrary files at LOCAL_ABSPATH1 and
- * LOCAL_ABSPATH2, using the diff callbacks from CALLBACKS.
- * Use PATH as the name passed to diff callbacks.
- * FILE1_IS_EMPTY and FILE2_IS_EMPTY are used as hints which diff callback
- * function to use to compare the files (added/deleted/changed).
- *
- * If ORIGINAL_PROPS_OVERRIDE is not NULL, use it as original properties
- * instead of reading properties from LOCAL_ABSPATH1. This is required when
- * a file replaces a directory, where LOCAL_ABSPATH1 is an empty file that
- * file content must be diffed against, but properties to diff against come
- * from the replaced directory. */
-static svn_error_t *
-do_arbitrary_files_diff(const char *local_abspath1,
-                        const char *local_abspath2,
-                        const char *path,
-                        svn_boolean_t file1_is_empty,
-                        svn_boolean_t file2_is_empty,
-                        apr_hash_t *original_props_override,
-                        const svn_wc_diff_callbacks4_t *callbacks,
-                        struct diff_cmd_baton *diff_cmd_baton,
-                        svn_client_ctx_t *ctx,
-                        apr_pool_t *scratch_pool)
-{
-  apr_hash_t *original_props;
-  apr_hash_t *modified_props;
-  apr_array_header_t *prop_changes;
-  svn_string_t *original_mime_type = NULL;
-  svn_string_t *modified_mime_type = NULL;
-
-  if (ctx->cancel_func)
-    SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
-  if (diff_cmd_baton->ignore_properties)
-    {
-      original_props = apr_hash_make(scratch_pool);
-      modified_props = apr_hash_make(scratch_pool);
-    }
-  else
-    {
-      /* Try to get properties from either file. It's OK if the files do not
-       * have properties, or if they are unversioned. */
-      if (original_props_override)
-        original_props = original_props_override;
-      else
-        SVN_ERR(get_props(&original_props, local_abspath1, ctx->wc_ctx,
-                          scratch_pool, scratch_pool));
-      SVN_ERR(get_props(&modified_props, local_abspath2, ctx->wc_ctx,
-                        scratch_pool, scratch_pool));
-    }
-
-  SVN_ERR(svn_prop_diffs(&prop_changes, modified_props, original_props,
-                         scratch_pool));
-
-  if (!diff_cmd_baton->force_binary)
-    {
-      /* Try to determine the mime-type of each file. */
-      original_mime_type = apr_hash_get(original_props, SVN_PROP_MIME_TYPE,
-                                        APR_HASH_KEY_STRING);
-      if (!file1_is_empty && !original_mime_type)
-        {
-          const char *mime_type;
-          SVN_ERR(svn_io_detect_mimetype2(&mime_type, local_abspath1,
-                                          ctx->mimetypes_map, scratch_pool));
-
-          if (mime_type)
-            original_mime_type = svn_string_create(mime_type, scratch_pool);
-        }
-
-      modified_mime_type = apr_hash_get(modified_props, SVN_PROP_MIME_TYPE,
-                                        APR_HASH_KEY_STRING);
-      if (!file2_is_empty && !modified_mime_type)
-        {
-          const char *mime_type;
-          SVN_ERR(svn_io_detect_mimetype2(&mime_type, local_abspath1,
-                                          ctx->mimetypes_map, scratch_pool));
-
-          if (mime_type)
-            modified_mime_type = svn_string_create(mime_type, scratch_pool);
-        }
-    }
-
-  /* Produce the diff. */
-  if (file1_is_empty && !file2_is_empty)
-    SVN_ERR(callbacks->file_added(NULL, NULL, NULL, path,
-                                  local_abspath1, local_abspath2,
-                                  /* ### TODO get real revision info
-                                   * for versioned files? */
-                                  SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
-                                  original_mime_type ?
-                                    original_mime_type->data : NULL,
-                                  modified_mime_type ?
-                                    modified_mime_type->data : NULL,
-                                  /* ### TODO get copyfrom? */
-                                  NULL, SVN_INVALID_REVNUM,
-                                  prop_changes, original_props,
-                                  diff_cmd_baton, scratch_pool));
-  else if (!file1_is_empty && file2_is_empty)
-    SVN_ERR(callbacks->file_deleted(NULL, NULL, path,
-                                    local_abspath1, local_abspath2,
-                                    original_mime_type ?
-                                      original_mime_type->data : NULL,
-                                    modified_mime_type ?
-                                      modified_mime_type->data : NULL,
-                                    original_props,
-                                    diff_cmd_baton, scratch_pool));
-  else
-    SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, path,
-                                    local_abspath1, local_abspath2,
-                                    /* ### TODO get real revision info
-                                     * for versioned files? */
-                                    SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
-                                    original_mime_type ?
-                                      original_mime_type->data : NULL,
-                                    modified_mime_type ?
-                                      modified_mime_type->data : NULL,
-                                    prop_changes, original_props,
-                                    diff_cmd_baton, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-struct arbitrary_diff_walker_baton {
-  /* The root directories of the trees being compared. */
-  const char *root1_abspath;
-  const char *root2_abspath;
-
-  /* TRUE if recursing within an added subtree of root2_abspath that
-   * does not exist in root1_abspath. */
-  svn_boolean_t recursing_within_added_subtree;
-
-  /* TRUE if recursing within an administrative (.i.e. .svn) directory. */
-  svn_boolean_t recursing_within_adm_dir;
-
-  /* The absolute path of the adm dir if RECURSING_WITHIN_ADM_DIR is TRUE.
-   * Else this is NULL.*/
-  const char *adm_dir_abspath;
-
-  /* A path to an empty file used for diffs that add/delete files. */
-  const char *empty_file_abspath;
-
-  const svn_wc_diff_callbacks4_t *callbacks;
-  struct diff_cmd_baton *callback_baton;
-  svn_client_ctx_t *ctx;
-  apr_pool_t *pool;
-} arbitrary_diff_walker_baton;
-
-/* Forward declaration needed because this function has a cyclic
- * dependency with do_arbitrary_dirs_diff(). */
-static svn_error_t *
-arbitrary_diff_walker(void *baton, const char *local_abspath,
-                      const apr_finfo_t *finfo,
-                      apr_pool_t *scratch_pool);
-
-/* Produce a diff between two arbitrary directories at LOCAL_ABSPATH1 and
- * LOCAL_ABSPATH2, using the provided diff callbacks to show file changes
- * and, for versioned nodes, property changes.
- *
- * If ROOT_ABSPATH1 and ROOT_ABSPATH2 are not NULL, show paths in diffs
- * relative to these roots, rather than relative to LOCAL_ABSPATH1 and
- * LOCAL_ABSPATH2. This is needed when crawling a subtree that exists
- * only within LOCAL_ABSPATH2. */
-static svn_error_t *
-do_arbitrary_dirs_diff(const char *local_abspath1,
-                       const char *local_abspath2,
-                       const char *root_abspath1,
-                       const char *root_abspath2,
-                       const svn_wc_diff_callbacks4_t *callbacks,
-                       struct diff_cmd_baton *callback_baton,
-                       svn_client_ctx_t *ctx,
-                       apr_pool_t *scratch_pool)
-{
-  apr_file_t *empty_file;
-  svn_node_kind_t kind1;
-
-  struct arbitrary_diff_walker_baton b;
-
-  /* If LOCAL_ABSPATH1 is not a directory, crawl LOCAL_ABSPATH2 instead
-   * and compare it to LOCAL_ABSPATH1, showing only additions.
-   * This case can only happen during recursion from arbitrary_diff_walker(),
-   * because do_arbitrary_nodes_diff() prevents this from happening at
-   * the root of the comparison. */
-  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
-  b.recursing_within_added_subtree = (kind1 != svn_node_dir);
-
-  b.root1_abspath = root_abspath1 ? root_abspath1 : local_abspath1;
-  b.root2_abspath = root_abspath2 ? root_abspath2 : local_abspath2;
-  b.recursing_within_adm_dir = FALSE;
-  b.adm_dir_abspath = NULL;
-  b.callbacks = callbacks;
-  b.callback_baton = callback_baton;
-  b.ctx = ctx;
-  b.pool = scratch_pool;
-
-  SVN_ERR(svn_io_open_unique_file3(&empty_file, &b.empty_file_abspath,
-                                   NULL, svn_io_file_del_on_pool_cleanup,
-                                   scratch_pool, scratch_pool));
-
-  SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
-                                                            : local_abspath1,
-                           0, arbitrary_diff_walker, &b, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* An implementation of svn_io_walk_func_t.
- * Note: LOCAL_ABSPATH is the path being crawled and can be on either side
- * of the diff depending on baton->recursing_within_added_subtree. */
-static svn_error_t *
-arbitrary_diff_walker(void *baton, const char *local_abspath,
-                      const apr_finfo_t *finfo,
-                      apr_pool_t *scratch_pool)
-{
-  struct arbitrary_diff_walker_baton *b = baton;
-  const char *local_abspath1;
-  const char *local_abspath2;
-  svn_node_kind_t kind1;
-  svn_node_kind_t kind2;
-  const char *child_relpath;
-  apr_hash_t *dirents1;
-  apr_hash_t *dirents2;
-  apr_hash_t *merged_dirents;
-  apr_array_header_t *sorted_dirents;
-  int i;
-  apr_pool_t *iterpool;
-
-  if (b->ctx->cancel_func)
-    SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
-
-  if (finfo->filetype != APR_DIR)
-    return SVN_NO_ERROR;
-
-  if (b->recursing_within_adm_dir)
-    {
-      if (svn_dirent_skip_ancestor(b->adm_dir_abspath, local_abspath))
-        return SVN_NO_ERROR;
-      else
-        {
-          b->recursing_within_adm_dir = FALSE;
-          b->adm_dir_abspath = NULL;
-        }
-    }
-  else if (strcmp(svn_dirent_basename(local_abspath, scratch_pool),
-                  SVN_WC_ADM_DIR_NAME) == 0)
-    {
-      b->recursing_within_adm_dir = TRUE;
-      b->adm_dir_abspath = apr_pstrdup(b->pool, local_abspath);
-      return SVN_NO_ERROR;
-    }
-
-  if (b->recursing_within_added_subtree)
-    child_relpath = svn_dirent_skip_ancestor(b->root2_abspath, local_abspath);
-  else
-    child_relpath = svn_dirent_skip_ancestor(b->root1_abspath, local_abspath);
-  if (!child_relpath)
-    return SVN_NO_ERROR;
-
-  local_abspath1 = svn_dirent_join(b->root1_abspath, child_relpath,
-                                   scratch_pool);
-  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
-
-  local_abspath2 = svn_dirent_join(b->root2_abspath, child_relpath,
-                                   scratch_pool);
-  SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool));
-
-  if (kind1 == svn_node_dir)
-    SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1,
-                                TRUE, /* only_check_type */
-                                scratch_pool, scratch_pool));
-  else
-    dirents1 = apr_hash_make(scratch_pool);
-
-  if (kind2 == svn_node_dir)
-    {
-      apr_hash_t *original_props;
-      apr_hash_t *modified_props;
-      apr_array_header_t *prop_changes;
-
-      /* Show any property changes for this directory. */
-      SVN_ERR(get_props(&original_props, local_abspath1, b->ctx->wc_ctx,
-                        scratch_pool, scratch_pool));
-      SVN_ERR(get_props(&modified_props, local_abspath2, b->ctx->wc_ctx,
-                        scratch_pool, scratch_pool));
-      SVN_ERR(svn_prop_diffs(&prop_changes, modified_props, original_props,
-                             scratch_pool));
-      if (prop_changes->nelts > 0)
-        SVN_ERR(diff_props_changed(NULL, NULL, child_relpath,
-                                   b->callback_baton->revnum1,
-                                   b->callback_baton->revnum2,
-                                   b->recursing_within_added_subtree,
-                                   prop_changes, original_props, TRUE,
-                                   b->callback_baton, scratch_pool));
-
-      /* Read directory entries. */
-      SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2,
-                                  TRUE, /* only_check_type */
-                                  scratch_pool, scratch_pool));
-    }
-  else
-    dirents2 = apr_hash_make(scratch_pool);
-
-  /* Compare dirents1 to dirents2 and show added/deleted/changed files. */
-  merged_dirents = apr_hash_merge(scratch_pool, dirents1, dirents2,
-                                  NULL, NULL);
-  sorted_dirents = svn_sort__hash(merged_dirents,
-                                  svn_sort_compare_items_as_paths,
-                                  scratch_pool);
-  iterpool = svn_pool_create(scratch_pool);
-  for (i = 0; i < sorted_dirents->nelts; i++)
-    {
-      svn_sort__item_t elt = APR_ARRAY_IDX(sorted_dirents, i, svn_sort__item_t);
-      const char *name = elt.key;
-      svn_io_dirent2_t *dirent1;
-      svn_io_dirent2_t *dirent2;
-      const char *child1_abspath;
-      const char *child2_abspath;
-
-      svn_pool_clear(iterpool);
-
-      if (b->ctx->cancel_func)
-        SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
-
-      if (strcmp(name, SVN_WC_ADM_DIR_NAME) == 0)
-        continue;
-
-      dirent1 = apr_hash_get(dirents1, name, APR_HASH_KEY_STRING);
-      if (!dirent1)
-        {
-          dirent1 = svn_io_dirent2_create(iterpool);
-          dirent1->kind = svn_node_none;
-        }
-      dirent2 = apr_hash_get(dirents2, name, APR_HASH_KEY_STRING);
-      if (!dirent2)
-        {
-          dirent2 = svn_io_dirent2_create(iterpool);
-          dirent2->kind = svn_node_none;
-        }
-
-      child1_abspath = svn_dirent_join(local_abspath1, name, iterpool);
-      child2_abspath = svn_dirent_join(local_abspath2, name, iterpool);
-
-      if (dirent1->special)
-        SVN_ERR(svn_io_check_resolved_path(child1_abspath, &dirent1->kind,
-                                           iterpool));
-      if (dirent2->special)
-        SVN_ERR(svn_io_check_resolved_path(child1_abspath, &dirent2->kind,
-                                           iterpool));
-
-      if (dirent1->kind == svn_node_dir &&
-          dirent2->kind == svn_node_dir)
-        continue;
-
-      /* Files that exist only in dirents1. */
-      if (dirent1->kind == svn_node_file &&
-          (dirent2->kind == svn_node_dir || dirent2->kind == svn_node_none))
-        SVN_ERR(do_arbitrary_files_diff(child1_abspath, b->empty_file_abspath,
-                                        svn_relpath_join(child_relpath, name,
-                                                         iterpool),
-                                        FALSE, TRUE, NULL,
-                                        b->callbacks, b->callback_baton,
-                                        b->ctx, iterpool));
-
-      /* Files that exist only in dirents2. */
-      if (dirent2->kind == svn_node_file &&
-          (dirent1->kind == svn_node_dir || dirent1->kind == svn_node_none))
-        {
-          apr_hash_t *original_props;
-
-          SVN_ERR(get_props(&original_props, child1_abspath, b->ctx->wc_ctx,
-                            scratch_pool, scratch_pool));
-          SVN_ERR(do_arbitrary_files_diff(b->empty_file_abspath, child2_abspath,
-                                          svn_relpath_join(child_relpath, name,
-                                                           iterpool),
-                                          TRUE, FALSE, original_props,
-                                          b->callbacks, b->callback_baton,
-                                          b->ctx, iterpool));
-        }
-
-      /* Files that exist in dirents1 and dirents2. */
-      if (dirent1->kind == svn_node_file && dirent2->kind == svn_node_file)
-        SVN_ERR(do_arbitrary_files_diff(child1_abspath, child2_abspath,
-                                        svn_relpath_join(child_relpath, name,
-                                                         iterpool),
-                                        FALSE, FALSE, NULL,
-                                        b->callbacks, b->callback_baton,
-                                        b->ctx, scratch_pool));
-
-      /* Directories that only exist in dirents2. These aren't crawled
-       * by this walker so we have to crawl them separately. */
-      if (dirent2->kind == svn_node_dir &&
-          (dirent1->kind == svn_node_file || dirent1->kind == svn_node_none))
-        SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath,
-                                       b->root1_abspath, b->root2_abspath,
-                                       b->callbacks, b->callback_baton,
-                                       b->ctx, iterpool));
-    }
-
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-/* Produce a diff between two files or two directories at LOCAL_ABSPATH1
- * and LOCAL_ABSPATH2, using the provided diff callbacks to show changes
- * in files. The files and directories involved may be part of a working
- * copy or they may be unversioned. For versioned files, show property
- * changes, too. */
-static svn_error_t *
-do_arbitrary_nodes_diff(const char *local_abspath1,
-                        const char *local_abspath2,
-                        const svn_wc_diff_callbacks4_t *callbacks,
-                        struct diff_cmd_baton *callback_baton,
-                        svn_client_ctx_t *ctx,
-                        apr_pool_t *scratch_pool)
-{
-  svn_node_kind_t kind1;
-  svn_node_kind_t kind2;
-
-  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
-  SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool));
-  if (kind1 != kind2)
-    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-                             _("'%s' is not the same node kind as '%s'"),
-                             local_abspath1, local_abspath2);
-
-  if (kind1 == svn_node_file)
-    SVN_ERR(do_arbitrary_files_diff(local_abspath1, local_abspath2,
-                                    svn_dirent_basename(local_abspath2,
-                                                        scratch_pool),
-                                    FALSE, FALSE, NULL,
-                                    callbacks, callback_baton,
-                                    ctx, scratch_pool));
-  else if (kind1 == svn_node_dir)
-    SVN_ERR(do_arbitrary_dirs_diff(local_abspath1, local_abspath2,
-                                   NULL, NULL,
-                                   callbacks, callback_baton,
-                                   ctx, scratch_pool));
-  else
-    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-                             _("'%s' is not a file or directory"),
-                             kind1 == svn_node_none ?
-                              local_abspath1 : local_abspath2);
-  return SVN_NO_ERROR;
-}
-
-
 /* Perform a diff between two working-copy paths.
 
    PATH1 and PATH2 are both working copy paths.  REVISION1 and
@@ -2068,18 +1593,17 @@ diff_wc_wc(const char *path1,
 
   SVN_ERR(svn_dirent_get_absolute(&abspath1, path1, pool));
 
+  /* Currently we support only the case where path1 and path2 are the
+     same path. */
   if ((strcmp(path1, path2) != 0)
       || (! ((revision1->kind == svn_opt_revision_base)
              && (revision2->kind == svn_opt_revision_working))))
-    {
-      const char *abspath2;
+    return unsupported_diff_error(
+       svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                        _("Only diffs between a path's text-base "
+                          "and its working files are supported at this time"
+                          )));
 
-      SVN_ERR(svn_dirent_get_absolute(&abspath2, path2, pool));
-      return svn_error_trace(do_arbitrary_nodes_diff(abspath1, abspath2,
-                                                     callbacks,
-                                                     callback_baton,
-                                                     ctx, pool));
-    }
 
   /* Resolve named revisions to real numbers. */
   err = svn_client__get_revision_number(&callback_baton->revnum1, NULL,
@@ -2976,10 +2500,26 @@ do_diff(const svn_wc_diff_callbacks4_t *
         }
       else /* path_or_url2 is a working copy path */
         {
-          SVN_ERR(diff_wc_wc(path_or_url1, revision1, path_or_url2, revision2,
-                             depth, ignore_ancestry, show_copies_as_adds,
-                             use_git_diff_format, changelists,
-                             callbacks, callback_baton, ctx, pool));
+          if (revision1->kind == svn_opt_revision_working
+              && revision2->kind == svn_opt_revision_working)
+            {
+              const char *abspath1;
+              const char *abspath2;
+
+              SVN_ERR(svn_dirent_get_absolute(&abspath1, path_or_url1, pool));
+              SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, pool));
+
+              SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ctx, pool));
+            }
+          else
+            SVN_ERR(diff_wc_wc(path_or_url1, revision1,
+                               path_or_url2, revision2,
+                               depth, ignore_ancestry, show_copies_as_adds,
+                               use_git_diff_format, changelists,
+                               callbacks, callback_baton, ctx, pool));
         }
     }
 



Mime
View raw message