⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diff.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
  /* Check to see if this entry is scheduled to be deleted, if so,
     then we need to remember so that we don't attempt to open the
     non-existent file when doing the final diff. */
  if (entry && entry->schedule == svn_wc_schedule_delete)
    b->schedule_delete = TRUE;

  if (b->added)
    {
      /* An empty file is the starting point if the file is being added */
      SVN_ERR (svn_wc__open_empty_file (&b->original_file, b->wc_path,
                                        b->pool));
    }
  else
    {
      /* The current text-base is the starting point if replacing */
      SVN_ERR (svn_wc__open_text_base (&b->original_file, b->wc_path,
                                       APR_READ, b->pool));
    }

  /* This is the file that will contain the pristine repository version. It
     is created in the admin temporary area. This file continues to exists
     until after the diff callback is run, at which point it is deleted. */ 
  SVN_ERR (svn_wc__open_text_base (&b->temp_file, b->wc_path,
                                   (APR_WRITE | APR_TRUNCATE | APR_CREATE),
                                   b->pool));

  /* Need to ensure that the above file gets removed if the program aborts
     with some error. So register a pool cleanup handler to delete the
     file. This handler is removed just before deleting the file. */
  apr_pool_cleanup_register (b->pool, file_baton, temp_file_cleanup_handler,
                             temp_file_cleanup_handler_remover);

  {
    const char *tmp_path;

    apr_file_name_get (&tmp_path, b->temp_file);
    svn_txdelta_apply (svn_stream_from_aprfile (b->original_file, b->pool),
                       svn_stream_from_aprfile (b->temp_file, b->pool),
                       NULL,
                       tmp_path,
                       b->pool,
                       &b->apply_handler, &b->apply_baton);
  }

  *handler = window_handler;
  *handler_baton = file_baton;
  return SVN_NO_ERROR;
}

/* An editor function.  When the file is closed we have a temporary
 * file containing a pristine version of the repository file. This can
 * be compared against the working copy.
 *
 * Ignore TEXT_CHECKSUM.
 */
static svn_error_t *
close_file (void *file_baton,
            const char *text_checksum,
            apr_pool_t *pool)
{
  struct file_baton *b = file_baton;
  struct edit_baton *eb = b->edit_baton;
  svn_wc_adm_access_t *adm_access;
  const svn_wc_entry_t *entry;
  const char *pristine_mimetype, *working_mimetype;

  /* The path to the temporary copy of the pristine repository version. */
  const char *temp_file_path
    = svn_wc__text_base_path (b->wc_path, TRUE, b->pool);
  SVN_ERR (svn_wc_adm_probe_retrieve (&adm_access, b->edit_baton->anchor,
                                      b->wc_path, b->pool));
  SVN_ERR (svn_wc_entry (&entry, b->wc_path, adm_access, FALSE, b->pool));

  /* We want to figure out if the file from the repository has an
     svn:mime-type.  So first look for svn:mime-type in
     b->propchanges... if not there, look for it in the *pristine*
     properties of path. */
  SVN_ERR (get_local_mimetypes (&pristine_mimetype, &working_mimetype,
                                b, adm_access, b->wc_path, pool));

  if (b->added)
    {
      /* Remember that the default diff order is to show repos->wc,
         but we ask the server for a wc->repos diff.  So if
         'reverse_order' is TRUE, then we do what the server says:
         show an add. */
      if (eb->reverse_order)
        SVN_ERR (b->edit_baton->callbacks->file_added
                 (NULL, NULL, b->path,
                  svn_wc__empty_file_path (b->wc_path, b->pool),
                  temp_file_path,
                  0, 
                  entry ? entry->revision : SVN_INVALID_REVNUM,
                  NULL,
                  pristine_mimetype,
                  b->edit_baton->callback_baton));
      else
      /* Add is required to change working-copy into requested revision, so
         diff should show this as a delete. Thus compare the repository
         file against the empty file. */
        SVN_ERR (b->edit_baton->callbacks->file_deleted
                 (NULL, NULL, b->path,
                  temp_file_path,
                  svn_wc__empty_file_path (b->wc_path, b->pool),
                  pristine_mimetype,
                  NULL,
                  b->edit_baton->callback_baton));
    }
  else
    {
      if (b->temp_file) /* A props-only change will not have opened a file */
        {
          /* Be careful with errors to ensure that the temporary translated
             file is deleted. */
          svn_error_t *err1, *err2 = SVN_NO_ERROR;
          const char *localfile;

          if (eb->use_text_base)
            localfile = svn_wc__text_base_path (b->path, FALSE, b->pool);
          else if (b->schedule_delete)
            localfile = svn_wc__empty_file_path (b->wc_path, b->pool);
          else
            /* a detranslated version of the working file */
            SVN_ERR (svn_wc_translated_file (&localfile, b->path, adm_access,
                                             TRUE, b->pool));

          err1 = b->edit_baton->callbacks->file_changed
            (NULL, NULL,
             b->path,
             eb->reverse_order ? localfile : temp_file_path,
             eb->reverse_order ? temp_file_path : localfile,
             b->edit_baton->revnum,
             SVN_INVALID_REVNUM,
             eb->reverse_order ? working_mimetype : pristine_mimetype,
             eb->reverse_order ? pristine_mimetype: working_mimetype,
             b->edit_baton->callback_baton);
      
          if ((! eb->use_text_base) && (! b->schedule_delete))
            if (localfile != b->path)
              err2 = svn_io_remove_file (localfile, b->pool);

          if (err1 || err2)
            {
              if (err1 && err2)
                svn_error_clear (err2);
              return err1 ? err1 : err2;
            }
        }
      
      if (b->propchanges->nelts > 0)
        {
          if (! eb->reverse_order)
            reverse_propchanges (b->baseprops, b->propchanges, b->pool);

          SVN_ERR (b->edit_baton->callbacks->props_changed
                   (NULL, NULL,
                    b->path,
                    b->propchanges,
                    b->baseprops,
                    b->edit_baton->callback_baton));
        }
    }

  return SVN_NO_ERROR;
}


static svn_error_t *
change_file_prop (void *file_baton,
                  const char *name,
                  const svn_string_t *value,
                  apr_pool_t *pool)
{
  struct file_baton *b = file_baton;
  svn_prop_t *propchange;

  propchange = apr_array_push (b->propchanges);
  propchange->name = apr_pstrdup (b->pool, name);
  propchange->value = value ? svn_string_dup (value, b->pool) : NULL;
  
  /* Read the baseprops if you haven't already. */
  if (! b->fetched_baseprops)
    load_base_props (b);

  return SVN_NO_ERROR;
}


/* An editor function. */
static svn_error_t *
change_dir_prop (void *dir_baton,
                 const char *name,
                 const svn_string_t *value,
                 apr_pool_t *pool)
{
  struct dir_baton *db = dir_baton;
  svn_prop_t *propchange;

  propchange = apr_array_push (db->propchanges);
  propchange->name = apr_pstrdup (db->pool, name);
  propchange->value = value ? svn_string_dup (value, db->pool) : NULL;

  /* Read the baseprops if you haven't already. */
  if (! db->fetched_baseprops)
    {
      /* the 'base' props to compare against, in this case, are
         actually the working props.  that's what we do with texts,
         anyway, in the 'svn diff -rN foo' case.  */

      /* also notice we're ignoring error here;  there's a chance that
         this path might not exist in the working copy, in which case
         the baseprops remains an empty hash. */
      svn_error_t *err = svn_wc_prop_list (&(db->baseprops), db->path,
                                           db->edit_baton->anchor, db->pool);
      if (err)
        svn_error_clear (err);
      db->fetched_baseprops = TRUE;
    }

  return SVN_NO_ERROR;
}


/* An editor function. */
static svn_error_t *
close_edit (void *edit_baton,
            apr_pool_t *pool)
{
  struct edit_baton *eb = edit_baton;

  if (!eb->root_opened)
    {
      struct dir_baton *b;

      b = make_dir_baton (eb->anchor_path, NULL, eb, FALSE, eb->pool);
      SVN_ERR (directory_elements_diff (b, FALSE));
    }

  return SVN_NO_ERROR;
}

/* Public Interface */


/* Create a diff editor and baton. */
svn_error_t *
svn_wc_get_diff_editor2 (svn_wc_adm_access_t *anchor,
                         const char *target,
                         const svn_wc_diff_callbacks_t *callbacks,
                         void *callback_baton,
                         svn_boolean_t recurse,
                         svn_boolean_t ignore_ancestry,
                         svn_boolean_t use_text_base,
                         svn_boolean_t reverse_order,
                         svn_cancel_func_t cancel_func,
                         void *cancel_baton,
                         const svn_delta_editor_t **editor,
                         void **edit_baton,
                         apr_pool_t *pool)
{
  struct edit_baton *eb;
  svn_delta_editor_t *tree_editor;

  eb = make_editor_baton (anchor, target, callbacks, callback_baton,
                          recurse, ignore_ancestry, use_text_base,
                          reverse_order, pool);
  tree_editor = svn_delta_default_editor (eb->pool);

  tree_editor->set_target_revision = set_target_revision;
  tree_editor->open_root = open_root;
  tree_editor->delete_entry = delete_entry;
  tree_editor->add_directory = add_directory;
  tree_editor->open_directory = open_directory;
  tree_editor->close_directory = close_directory;
  tree_editor->add_file = add_file;
  tree_editor->open_file = open_file;
  tree_editor->apply_textdelta = apply_textdelta;
  tree_editor->change_file_prop = change_file_prop;
  tree_editor->change_dir_prop = change_dir_prop;
  tree_editor->close_file = close_file;
  tree_editor->close_edit = close_edit;

  SVN_ERR (svn_delta_get_cancellation_editor (cancel_func,
                                              cancel_baton,
                                              tree_editor,
                                              eb,
                                              editor,
                                              edit_baton,
                                              pool));

  return SVN_NO_ERROR;
}

svn_error_t *
svn_wc_get_diff_editor (svn_wc_adm_access_t *anchor,
                        const char *target,
                        const svn_wc_diff_callbacks_t *callbacks,
                        void *callback_baton,
                        svn_boolean_t recurse,
                        svn_boolean_t use_text_base,
                        svn_boolean_t reverse_order,
                        svn_cancel_func_t cancel_func,
                        void *cancel_baton,
                        const svn_delta_editor_t **editor,
                        void **edit_baton,
                        apr_pool_t *pool)
{
  return svn_wc_get_diff_editor2 (anchor, target, callbacks, callback_baton,
                                  recurse, FALSE, use_text_base, reverse_order,
                                  cancel_func, cancel_baton,
                                  editor, edit_baton, pool);
}


/* Compare working copy against the text-base. */
svn_error_t *
svn_wc_diff2 (svn_wc_adm_access_t *anchor,
              const char *target,
              const svn_wc_diff_callbacks_t *callbacks,
              void *callback_baton,
              svn_boolean_t recurse,
              svn_boolean_t ignore_ancestry,
              apr_pool_t *pool)
{
  struct edit_baton *eb;
  struct dir_baton *b;
  const svn_wc_entry_t *entry;
  const char *target_path;
  svn_wc_adm_access_t *adm_access;

  eb = make_editor_baton (anchor, target, callbacks, callback_baton,
                          recurse, ignore_ancestry, FALSE, FALSE, pool);

  target_path = svn_path_join (svn_wc_adm_access_path (anchor), target,
                               eb->pool);

  SVN_ERR (svn_wc_adm_probe_retrieve (&adm_access, anchor, target_path,
                                      eb->pool));
  SVN_ERR (svn_wc_entry (&entry, target_path, adm_access, FALSE, eb->pool));

  if (entry->kind == svn_node_dir)
    b = make_dir_baton (target_path, NULL, eb, FALSE, eb->pool);
  else
    b = make_dir_baton (eb->anchor_path, NULL, eb, FALSE, eb->pool);

  SVN_ERR (directory_elements_diff (b, FALSE));

  return SVN_NO_ERROR;
}


svn_error_t *
svn_wc_diff (svn_wc_adm_access_t *anchor,
             const char *target,
             const svn_wc_diff_callbacks_t *callbacks,
             void *callback_baton,
             svn_boolean_t recurse,
             apr_pool_t *pool)
{
  return svn_wc_diff2 (anchor, target, callbacks, callback_baton,
                       recurse, FALSE, pool);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -