FreeBSD/contrib/subversion/subversion/libsvn_client/diff.c
/* Perform a diff between two repository paths.

   PATH_OR_URL1 and PATH_OR_URL2 may be either URLs or the working copy paths.
   REVISION1 and REVISION2 are their respective revisions.
   If PEG_REVISION is specified, PATH_OR_URL2 is the path at the peg revision,
   and the actual two paths compared are determined by following copy
   history from PATH_OR_URL2.

   All other options are the same as those passed to svn_client_diff6(). */
Perform a diff between two repository paths.
PATH_OR_URL1 and PATH_OR_URL2 may be either URLs or the working copy paths.
REVISION1 and REVISION2 are their respective revisions.
If PEG_REVISION is specified, PATH_OR_URL2 is the path at the peg revision,
and the actual two paths compared are determined by following copy
history from PATH_OR_URL2.

All other options are the same as those passed to svn_client_diff6().
Perform a diff between two repository paths . PATH_OR_URL1 and PATH_OR_URL2 may be either URLs or the working copy paths . REVISION1 and REVISION2 are their respective revisions . If PEG_REVISION is specified PATH_OR_URL2 is the path at the peg revision and the actual two paths compared are determined by following copy history from PATH_OR_URL2 . All other options are the same as those passed to svn_client_diff6 () .
static svn_error_t *
diff_repos_repos(const char **root_relpath,
                 svn_boolean_t *root_is_dir,
                 struct diff_driver_info_t *ddi,
                 const char *path_or_url1,
                 const char *path_or_url2,
                 const svn_opt_revision_t *revision1,
                 const svn_opt_revision_t *revision2,
                 const svn_opt_revision_t *peg_revision,
                 svn_depth_t depth,
                 svn_boolean_t ignore_ancestry,
                 svn_boolean_t text_deltas,
                 const svn_diff_tree_processor_t *diff_processor,
                 svn_client_ctx_t *ctx,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
{
  svn_ra_session_t *extra_ra_session;
  const svn_ra_reporter3_t *reporter;
  void *reporter_baton;
  const svn_delta_editor_t *diff_editor;
  void *diff_edit_baton;
  const char *url1;
  const char *url2;
  svn_revnum_t rev1;
  svn_revnum_t rev2;
  svn_node_kind_t kind1;
  svn_node_kind_t kind2;
  const char *anchor1;
  const char *anchor2;
  const char *target1;
  const char *target2;
  svn_ra_session_t *ra_session;
  SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &rev1, &rev2,
                                   &anchor1, &anchor2, &target1, &target2,
                                   &kind1, &kind2, &ra_session,
                                   ctx, path_or_url1, path_or_url2,
                                   revision1, revision2, peg_revision,
                                   scratch_pool));
  if (ddi)
    {
      ddi->orig_path_1 = url1;
      ddi->orig_path_2 = url2;
      if (!svn_path_is_url(path_or_url2))
        ddi->anchor = path_or_url2;
      else if (!svn_path_is_url(path_or_url1))
        ddi->anchor = path_or_url1;
      else
        ddi->anchor = NULL;
      if (*target1 && ddi->anchor
          && (kind1 != svn_node_dir || kind2 != svn_node_dir))
        ddi->anchor = svn_dirent_dirname(ddi->anchor, result_pool);
    }
  if (kind2 == svn_node_none)
    {
      const char *str_tmp;
      svn_revnum_t rev_tmp;
      str_tmp = url2;
      url2 = url1;
      url1 = str_tmp;
      rev_tmp = rev2;
      rev2 = rev1;
      rev1 = rev_tmp;
      str_tmp = anchor2;
      anchor2 = anchor1;
      anchor1 = str_tmp;
      str_tmp = target2;
      target2 = target1;
      target1 = str_tmp;
      diff_processor = svn_diff__tree_processor_reverse_create(diff_processor,
                                                               NULL,
                                                               scratch_pool);
    }
  if (root_relpath)
    *root_relpath = apr_pstrdup(result_pool, target1);
  else if ((kind1 != svn_node_file && kind2 != svn_node_file)
           && target1[0] != '\0')
    {
      diff_processor = svn_diff__tree_processor_filter_create(
                                        diff_processor, target1, scratch_pool);
    }
  SVN_ERR(svn_ra__dup_session(&extra_ra_session, ra_session, anchor1,
                              scratch_pool, scratch_pool));
  if (ddi)
    {
      const char *repos_root_url;
      const char *session_url;
      SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url,
                                      scratch_pool));
      SVN_ERR(svn_ra_get_session_url(ra_session, &session_url,
                                      scratch_pool));
      ddi->session_relpath = svn_uri_skip_ancestor(repos_root_url,
                                                    session_url,
                                                    result_pool);
    }
  SVN_ERR(svn_client__get_diff_editor2(
                &diff_editor, &diff_edit_baton,
                extra_ra_session, depth,
                rev1,
                text_deltas,
                diff_processor,
                ctx->cancel_func, ctx->cancel_baton,
                scratch_pool));
  SVN_ERR(svn_ra_do_diff3(ra_session, &reporter, &reporter_baton,
                          rev2, target1,
                          depth, ignore_ancestry, text_deltas,
                          url2, diff_editor, diff_edit_baton, scratch_pool));
  SVN_ERR(reporter->set_path(reporter_baton, "", rev1,
                             svn_depth_infinity,
                             FALSE, NULL,
                             scratch_pool));
  return svn_error_trace(
                  reporter->finish_report(reporter_baton, scratch_pool));
}
static svn_error_t * diff_repos_repos ( const char * * root_relpath , svn_boolean_t * root_is_dir , struct diff_driver_info_t * ddi , const char * path_or_url1 , const char * path_or_url2 , const svn_opt_revision_t * revision1 , const svn_opt_revision_t * revision2 , const svn_opt_revision_t * peg_revision , svn_depth_t depth , svn_boolean_t ignore_ancestry , svn_boolean_t text_deltas , const svn_diff_tree_processor_t * diff_processor , svn_client_ctx_t * ctx , apr_pool_t * result_pool , apr_pool_t * scratch_pool ) { svn_ra_session_t * extra_ra_session ; const svn_ra_reporter3_t * reporter ; void * reporter_baton ; const svn_delta_editor_t * diff_editor ; void * diff_edit_baton ; const char * url1 ; const char * url2 ; svn_revnum_t rev1 ; svn_revnum_t rev2 ; svn_node_kind_t kind1 ; svn_node_kind_t kind2 ; const char * anchor1 ; const char * anchor2 ; const char * target1 ; const char * target2 ; svn_ra_session_t * ra_session ; SVN_ERR ( diff_prepare_repos_repos ( & url1 , & url2 , & rev1 , & rev2 , & anchor1 , & anchor2 , & target1 , & target2 , & kind1 , & kind2 , & ra_session , ctx , path_or_url1 , path_or_url2 , revision1 , revision2 , peg_revision , scratch_pool ) ) ; if ( ddi ) { ddi -> orig_path_1 = url1 ; ddi -> orig_path_2 = url2 ; if ( ! svn_path_is_url ( path_or_url2 ) ) ddi -> anchor = path_or_url2 ; else if ( ! svn_path_is_url ( path_or_url1 ) ) ddi -> anchor = path_or_url1 ; else ddi -> anchor = NULL ; if ( * target1 && ddi -> anchor && ( kind1 != svn_node_dir || kind2 != svn_node_dir ) ) ddi -> anchor = svn_dirent_dirname ( ddi -> anchor , result_pool ) ; } if ( kind2 == svn_node_none ) { const char * str_tmp ; svn_revnum_t rev_tmp ; str_tmp = url2 ; url2 = url1 ; url1 = str_tmp ; rev_tmp = rev2 ; rev2 = rev1 ; rev1 = rev_tmp ; str_tmp = anchor2 ; anchor2 = anchor1 ; anchor1 = str_tmp ; str_tmp = target2 ; target2 = target1 ; target1 = str_tmp ; diff_processor = svn_diff__tree_processor_reverse_create ( diff_processor , NULL , scratch_pool ) ; } if ( root_relpath ) * root_relpath = apr_pstrdup ( result_pool , target1 ) ; else if ( ( kind1 != svn_node_file && kind2 != svn_node_file ) && target1 [ 0 ] != ' \0 ' ) { diff_processor = svn_diff__tree_processor_filter_create ( diff_processor , target1 , scratch_pool ) ; } SVN_ERR ( svn_ra__dup_session ( & extra_ra_session , ra_session , anchor1 , scratch_pool , scratch_pool ) ) ; if ( ddi ) { const char * repos_root_url ; const char * session_url ; SVN_ERR ( svn_ra_get_repos_root2 ( ra_session , & repos_root_url , scratch_pool ) ) ; SVN_ERR ( svn_ra_get_session_url ( ra_session , & session_url , scratch_pool ) ) ; ddi -> session_relpath = svn_uri_skip_ancestor ( repos_root_url , session_url , result_pool ) ; } SVN_ERR ( svn_client__get_diff_editor2 ( & diff_editor , & diff_edit_baton , extra_ra_session , depth , rev1 , text_deltas , diff_processor , ctx -> cancel_func , ctx -> cancel_baton , scratch_pool ) ) ; SVN_ERR ( svn_ra_do_diff3 ( ra_session , & reporter , & reporter_baton , rev2 , target1 , depth , ignore_ancestry , text_deltas , url2 , diff_editor , diff_edit_baton , scratch_pool ) ) ; SVN_ERR ( reporter -> set_path ( reporter_baton , " " , rev1 , svn_depth_infinity , FALSE , NULL , scratch_pool ) ) ; return svn_error_trace ( reporter -> finish_report ( reporter_baton , scratch_pool ) ) ; }
Perform a diff between two repository paths.
Perform a diff between two repository paths .
/* Prepare info for the repos repos diff. */ /* Set up the repos_diff editor on BASE_PATH, if available.
     Otherwise, we just use "". */ /* Get actual URLs. */ /* This should be moved to the diff writer
         - path_or_url are provided by the caller
         - target1 is available as *root_relpath
         - (kind1 != svn_node_dir || kind2 != svn_node_dir) = !*root_is_dir */ /* The repository can bring in a new working copy, but not delete
     everything. Luckily our new diff handler can just be reversed. */ /* Filter the first path component using a filter processor, until we fixed
     the diff processing to handle this directly */ /* Now, we open an extra RA session to the correct anchor
     location for URL1.  This is used during the editor calls to fetch file
     contents.  */ /* We want to switch our txn into URL2 */ /* Drive the reporter; do the diff. */