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

📄 repos_diff.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * repos_diff.c -- The diff editor for comparing two repository versions
 *
 * ====================================================================
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 */

/* This code uses an editor driven by a tree delta between two
 * repository revisions (REV1 and REV2). For each file encountered in
 * the delta the editor constructs two temporary files, one for each
 * revision. This necessitates a separate request for the REV1 version
 * of the file when the delta shows the file being modified or
 * deleted. Files that are added by the delta do not require a
 * separate request, the REV1 version is empty and the delta is
 * sufficient to construct the REV2 version. When both versions of
 * each file have been created the diff callback is invoked to display
 * the difference between the two files.  */

#include "svn_client.h"
#include "svn_wc.h"
#include "svn_pools.h"
#include "svn_path.h"
#include "svn_io.h"
#include "svn_utf.h"

#include "client.h"

/* Overall crawler editor baton.  */
struct edit_baton {
  /* TARGET is a working-copy directory which corresponds to the base
     URL open in RA_SESSION below. */
  const char *target;

  /* ADM_ACCESS is an access baton that includes the TARGET directory */
  svn_wc_adm_access_t *adm_access;

  /* The callback and calback argument that implement the file comparison
     function */
  const svn_wc_diff_callbacks_t *diff_callbacks;
  void *diff_cmd_baton;

  /* RECURSE is TRUE if this is a recursive diff or merge, false otherwise */
  svn_boolean_t recurse;

  /* DRY_RUN is TRUE if this is a dry-run diff, false otherwise. */
  svn_boolean_t dry_run;

  /* RA_LIB is the vtable for making requests to the RA layer, RA_SESSION
     is the open session for these requests */
  svn_ra_plugin_t *ra_lib;
  void *ra_session;

  /* The rev1 from the '-r Rev1:Rev2' command line option */
  svn_revnum_t revision;

  /* The rev2 from the '-r Rev1:Rev2' option, specifically set by
     set_target_revision(). */
  svn_revnum_t target_revision;

  /* A temporary empty file. Used for add/delete differences. This is
     cached here so that it can be reused, all empty files are the same. */
  const char *empty_file;

  /* If the func is non-null, send notifications of actions. */
  svn_wc_notify_func_t notify_func;
  void *notify_baton;

  apr_pool_t *pool;
};

/* Directory level baton.
 */
struct dir_baton {
  /* Gets set if the directory is added rather than replaced/unchanged. */
  svn_boolean_t added;

  /* The path of the directory within the repository */
  const char *path;

  /* The path of the directory in the wc, relative to cwd */
  const char *wcpath;

  /* The baton for the parent directory, or null if this is the root of the
     hierarchy to be compared. */
  struct dir_baton *dir_baton;

  /* The overall crawler editor baton. */
  struct edit_baton *edit_baton;

  /* A cache of any property changes (svn_prop_t) received for this dir. */
  apr_array_header_t *propchanges;

  /* The pristine-property list attached to this directory. */
  apr_hash_t *pristine_props;

  /* The pool passed in by add_dir, open_dir, or open_root.
     Also, the pool this dir baton is allocated in. */
  apr_pool_t *pool;
};

/* File level baton.
 */
struct file_baton {
  /* Gets set if the file is added rather than replaced. */
  svn_boolean_t added;

  /* The path of the file within the repository */
  const char *path;

  /* The path of the file in the wc, relative to cwd */
  const char *wcpath;

  /* The path and APR file handle to the temporary file that contains the
     first repository version.  Also, the pristine-property list of
     this file. */
  const char *path_start_revision;
  apr_file_t *file_start_revision;
  apr_hash_t *pristine_props;

  /* The path and APR file handle to the temporary file that contains the
     second repository version.  These fields are set when processing
     textdelta and file deletion, and will be NULL if there's no
     textual difference between the two revisions. */
  const char *path_end_revision;
  apr_file_t *file_end_revision;

  /* APPLY_HANDLER/APPLY_BATON represent the delta application baton. */
  svn_txdelta_window_handler_t apply_handler;
  void *apply_baton;

  /* The overall crawler editor baton. */
  struct edit_baton *edit_baton;

  /* A cache of any property changes (svn_prop_t) received for this file. */
  apr_array_header_t *propchanges;

  /* The pool passed in by add_file or open_file.
     Also, the pool this file_baton is allocated in. */
  apr_pool_t *pool;
};

/* Data used by the apr pool temp file cleanup handler */
struct temp_file_cleanup_s {
  /* The path to the file to be deleted.  NOTE: this path is
     APR-encoded, _not_ utf8-encoded! */
  const char *path;
  /* The pool to which the deletion of the file is linked. */
  apr_pool_t *pool;
};

/* Create a new directory baton for PATH in POOL.  ADDED is set if
 * this directory is being added rather than replaced. PARENT_BATON is
 * the baton of the parent directory, it will be null if this is the
 * root of the comparison hierarchy. The directory and its parent may
 * or may not exist in the working copy. EDIT_BATON is the overall
 * crawler editor baton.
 */
static struct dir_baton *
make_dir_baton (const char *path,
                struct dir_baton *parent_baton,
                svn_boolean_t added,
                apr_pool_t *pool)
{
  struct dir_baton *dir_baton = apr_pcalloc (pool, sizeof (*dir_baton));

  dir_baton->dir_baton = parent_baton;
  dir_baton->edit_baton = parent_baton->edit_baton;
  dir_baton->added = added;
  dir_baton->pool = pool;
  dir_baton->path = apr_pstrdup (pool, path);
  dir_baton->wcpath = svn_path_join (parent_baton->edit_baton->target,
                                     path, pool);
  dir_baton->propchanges  = apr_array_make (pool, 1, sizeof (svn_prop_t));

  return dir_baton;
}

/* Create a new file baton for PATH in POOL, which is a child of
 * directory PARENT_PATH. ADDED is set if this file is being added
 * rather than replaced.  EDIT_BATON is a pointer to the global edit
 * baton.
 */
static struct file_baton *
make_file_baton (const char *path,
                 svn_boolean_t added,
                 void *edit_baton,
                 apr_pool_t *pool)
{
  struct file_baton *file_baton = apr_pcalloc (pool, sizeof (*file_baton));
  struct edit_baton *eb = edit_baton;

  file_baton->edit_baton = edit_baton;
  file_baton->added = added;
  file_baton->pool = pool;
  file_baton->path = apr_pstrdup (pool, path);
  file_baton->wcpath = svn_path_join (eb->target, path, pool);
  file_baton->propchanges  = apr_array_make (pool, 1, sizeof (svn_prop_t));

  return file_baton;
}


/* Helper function: return up to two svn:mime-type values buried
 * within a file baton.  Set *MIMETYPE1 to the value within the file's
 * pristine properties, or NULL if not available.  Set *MIMETYPE2 to
 * the value within the "new" file's propchanges, or NULL if not
 * available.
 */
static void
get_file_mime_types (const char **mimetype1,
                     const char **mimetype2,
                     struct file_baton *b)
{
  /* Defaults */
  *mimetype1 = NULL;
  *mimetype2 = NULL;

  if (b->pristine_props)
    {
      svn_string_t *pristine_val;
      pristine_val = apr_hash_get (b->pristine_props, SVN_PROP_MIME_TYPE,
                                   strlen(SVN_PROP_MIME_TYPE));
      if (pristine_val)
        *mimetype1 = pristine_val->data;
    }

  if (b->propchanges)
    {
      int i;
      svn_prop_t *propchange;

      for (i = 0; i < b->propchanges->nelts; i++)
        {
          propchange = &APR_ARRAY_IDX(b->propchanges, i, svn_prop_t);
          if (strcmp (propchange->name, SVN_PROP_MIME_TYPE) == 0)
            {
              if (propchange->value)
                *mimetype2 = propchange->value->data;
              break;
            }
        }
    }
}


/* An apr pool cleanup handler, this deletes one of the temporary files.
 */
static apr_status_t
temp_file_plain_cleanup_handler (void *arg)
{
  struct temp_file_cleanup_s *s = arg;

  /* Note to UTF-8 watchers: this is ok because the path is already in
     APR internal encoding. */ 
  return apr_file_remove (s->path, s->pool);
}

/* An apr pool cleanup handler, this removes a cleanup handler.
 */
static apr_status_t
temp_file_child_cleanup_handler (void *arg)
{
  struct temp_file_cleanup_s *s = arg;

  apr_pool_cleanup_kill (s->pool, s, temp_file_plain_cleanup_handler);

  return APR_SUCCESS;
}

/* Register a pool cleanup to delete PATH when POOL is destroyed.
 *
 * PATH is not copied; caller should probably ensure that it is
 * allocated in a pool at least as long-lived as POOL.
 *
 * The main "gotcha" is that if the process forks a child by calling
 * apr_proc_create, then the child's copy of the cleanup handler will run
 * and delete the file while the parent still expects it to be around. To
 * avoid this a child cleanup handler is also installed to kill the plain
 * cleanup handler in the child.
 *
 * ### TODO: This a candidate to be a general utility function.
 */
static svn_error_t *
temp_file_cleanup_register (const char *path,
                            apr_pool_t *pool)
{
  struct temp_file_cleanup_s *s = apr_palloc (pool, sizeof (*s));
  SVN_ERR (svn_path_cstring_from_utf8 (&(s->path), path, pool));
  s->pool = pool;
  apr_pool_cleanup_register (s->pool, s, temp_file_plain_cleanup_handler,
                             temp_file_child_cleanup_handler);
  return SVN_NO_ERROR;
}


/* Get the repository version of a file. This makes an RA request to
 * retrieve the file contents. A pool cleanup handler is installed to
 * delete this file.
 *
 * ### TODO: The editor calls this function to get REV1 of the file. Can we
 * get the file props as well?  Then get_wc_prop() could return them later
 * on enabling the REV1:REV2 request to send diffs.
 */
static svn_error_t *
get_file_from_ra (struct file_baton *b)
{
  apr_file_t *file;
  svn_stream_t *fstream;
  const char *temp_dir;

  SVN_ERR (svn_io_temp_dir (&temp_dir, b->pool));
  SVN_ERR (svn_io_open_unique_file (&file, &(b->path_start_revision),
                                    svn_path_join (temp_dir, "tmp", b->pool),
                                    "", FALSE, b->pool));

  /* Install a pool cleanup handler to delete the file */
  SVN_ERR (temp_file_cleanup_register (b->path_start_revision, b->pool));

  fstream = svn_stream_from_aprfile (file, b->pool);
  SVN_ERR (b->edit_baton->ra_lib->get_file (b->edit_baton->ra_session,
                                            b->path,
                                            b->edit_baton->revision,
                                            fstream, NULL,
                                            &(b->pristine_props),
                                            b->pool));
  SVN_ERR (svn_io_file_close (file, b->pool));

⌨️ 快捷键说明

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