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

📄 main.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * main.c: Subversion server inspection tool.
 *
 * ====================================================================
 * 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/.
 * ====================================================================
 */

#include <assert.h>

#include <apr_general.h>
#include <apr_pools.h>
#include <apr_time.h>
#include <apr_thread_proc.h>
#include <apr_file_io.h>
#include <apr_signal.h>

#define APR_WANT_STDIO
#define APR_WANT_STRFUNC
#include <apr_want.h>

#include "svn_cmdline.h"
#include "svn_types.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_repos.h"
#include "svn_fs.h"
#include "svn_repos.h"
#include "svn_time.h"
#include "svn_utf.h"
#include "svn_subst.h"
#include "svn_opt.h"
#include "svn_props.h"
#include "svn_diff.h"

#include "svn_private_config.h"


/*** Some convenience macros and types. ***/


/* Option handling. */

static svn_opt_subcommand_t
  subcommand_author,
  subcommand_cat,
  subcommand_changed,
  subcommand_date,
  subcommand_diff,
  subcommand_dirschanged,
  subcommand_help,
  subcommand_history,
  subcommand_info,
  subcommand_log,
  subcommand_pget,
  subcommand_plist,
  subcommand_tree,
  subcommand_uuid,
  subcommand_youngest;

/* Option codes and descriptions. */
enum 
  { 
    svnlook__version = SVN_OPT_FIRST_LONGOPT_ID,
    svnlook__show_ids,
    svnlook__no_diff_deleted
  };

/*
 * This must not have more than SVN_OPT_MAX_OPTIONS entries; if you
 * need more, increase that limit first. 
 *
 * The entire list must be terminated with an entry of nulls.
 */
static const apr_getopt_option_t options_table[] =
  {
    {"help",          'h', 0,
     N_("show help on a subcommand")},

    {NULL,            '?', 0,
     N_("show help on a subcommand")},

    {"version",       svnlook__version, 0,
     N_("show version information")},

    {"revision",      'r', 1,
     N_("specify revision number ARG")},

    {"transaction",  't', 1,
     N_("specify transaction name ARG")},

    {"verbose",  'v', 0,
     N_("be verbose")},

    {"show-ids",      svnlook__show_ids, 0,
     N_("show node revision ids for each path")},

    {"no-diff-deleted", svnlook__no_diff_deleted, 0,
     N_("do not print differences for deleted files")},

    {0,               0, 0, 0}
  };


/* Array of available subcommands.
 * The entire list must be terminated with an entry of nulls.
 */
static const svn_opt_subcommand_desc_t cmd_table[] =
  {
    {"author", subcommand_author, {0},
     N_("usage: svnlook author REPOS_PATH\n\n"
        "Print the author.\n"),
     {'r', 't'} },
    
    {"cat", subcommand_cat, {0},
     N_("usage: svnlook cat REPOS_PATH FILE_PATH\n\n"
        "Print the contents of a file.  Leading '/' on FILE_PATH is "
        "optional.\n"),
     {'r', 't'} },
    
    {"changed", subcommand_changed, {0},
     N_("usage: svnlook changed REPOS_PATH\n\n"
        "Print the paths that were changed.\n"),
     {'r', 't'} },
    
    {"date", subcommand_date, {0},
     N_("usage: svnlook date REPOS_PATH\n\n"
        "Print the datestamp.\n"),
     {'r', 't'} },

    {"diff", subcommand_diff, {0},
     N_("usage: svnlook diff REPOS_PATH\n\n"
        "Print GNU-style diffs of changed files and properties.\n"),
     {'r', 't', svnlook__no_diff_deleted} },

    {"dirs-changed", subcommand_dirschanged, {0},
     N_("usage: svnlook dirs-changed REPOS_PATH\n\n"
        "Print the directories that were themselves changed (property edits)\n"
        "or whose file children were changed.\n"),
     {'r', 't'} },
    
    {"help", subcommand_help, {"?", "h"},
     N_("usage: svnlook help [SUBCOMMAND...]\n\n"
        "Describe the usage of this program or its subcommands.\n"),
     {svnlook__version} },

    {"history", subcommand_history, {0},
     N_("usage: svnlook history REPOS_PATH [PATH_IN_REPOS]\n\n"
        "Print information about the history of a path in the repository (or\n"
        "the root directory if no path is supplied).\n"),
     {'r', svnlook__show_ids} },

    {"info", subcommand_info, {0},
     N_("usage: svnlook info REPOS_PATH\n\n"
        "Print the author, datestamp, log message size, and log message.\n"),
     {'r', 't'} },

    {"log", subcommand_log, {0},
     N_("usage: svnlook log REPOS_PATH\n\n"
        "Print the log message.\n"),
     {'r', 't'} },

    {"propget", subcommand_pget, {"pget", "pg"},
     N_("usage: svnlook propget REPOS_PATH PROPNAME PATH_IN_REPOS\n\n"
        "Print the raw value of a property on a path in the repository.\n"),
     {'r', 't'} },

    {"proplist", subcommand_plist, {"plist", "pl"},
     N_("usage: svnlook proplist REPOS_PATH PATH_IN_REPOS\n\n"
        "List the properties of a path in the repository.\n"
        "With -v, show the property values too.\n"),
     {'r', 't', 'v'} },

    {"tree", subcommand_tree, {0},
     N_("usage: svnlook tree REPOS_PATH [PATH_IN_REPOS]\n\n"
        "Print the tree, starting at PATH_IN_REPOS (if supplied, at the root\n"
        "of the tree otherwise), optionally showing node revision ids.\n"),
     {'r', 't', svnlook__show_ids} },

    {"uuid", subcommand_uuid, {0},
     N_("usage: svnlook uuid REPOS_PATH\n\n"
        "Print the repository's UUID.\n"),
     {0} },

    {"youngest", subcommand_youngest, {0},
     N_("usage: svnlook youngest REPOS_PATH\n\n"
        "Print the youngest revision number.\n"),
     {0} },

    { NULL, NULL, {0}, NULL, {0} }
  };


/* Baton for passing option/argument state to a subcommand function. */
struct svnlook_opt_state
{
  const char *repos_path;  /* 'arg0' is always the path to the repository. */
  const char *arg1;        /* Usually an fs path, a propname, or NULL. */
  const char *arg2;        /* Usually an fs path or NULL. */
  svn_revnum_t rev;
  const char *txn;
  svn_boolean_t version;          /* --version */
  svn_boolean_t show_ids;         /* --show-ids */
  svn_boolean_t help;             /* --help */
  svn_boolean_t no_diff_deleted;  /* --no-diff-deleted */
  svn_boolean_t verbose;          /* --verbose */
};


typedef struct svnlook_ctxt_t
{
  svn_repos_t *repos;
  svn_fs_t *fs;
  svn_boolean_t is_revision;
  svn_boolean_t show_ids;
  svn_boolean_t no_diff_deleted;
  svn_revnum_t rev_id;
  svn_fs_txn_t *txn;
  const char *txn_name /* UTF-8! */;

} svnlook_ctxt_t;

/* A flag to see if we've been cancelled by the client or not. */
static volatile sig_atomic_t cancelled = FALSE;


/*** Helper functions. ***/

/* A signal handler to support cancellation. */
static void
signal_handler (int signum)
{
  apr_signal (signum, SIG_IGN);
  cancelled = TRUE;
}

/* Our cancellation callback. */
static svn_error_t *
check_cancel (void *baton)
{
  if (cancelled)
    return svn_error_create (SVN_ERR_CANCELLED, NULL, "Caught signal");
  else
    return SVN_NO_ERROR;
}


/* Version compatibility check */
static svn_error_t *
check_lib_versions (void)
{
  static const svn_version_checklist_t checklist[] =
    {
      { "svn_subr",  svn_subr_version },
      { "svn_repos", svn_repos_version },
      { "svn_fs",    svn_fs_version },
      { "svn_delta", svn_delta_version },
      { "svn_diff",  svn_diff_version },
      { NULL, NULL }
    };

   SVN_VERSION_DEFINE (my_version);
   return svn_ver_check_list (&my_version, checklist);
}


/* Get revision or transaction property PROP_NAME for the revision or
   transaction specified in C, allocating in in POOL and placing it in
   *PROP_VALUE. */
static svn_error_t *
get_property (svn_string_t **prop_value,
              svnlook_ctxt_t *c, 
              const char *prop_name,
              apr_pool_t *pool)
{
  svn_string_t *raw_value;

  /* Fetch transaction property... */
  if (! c->is_revision)
    SVN_ERR (svn_fs_txn_prop (&raw_value, c->txn, prop_name, pool));

  /* ...or revision property -- it's your call. */
  else
    SVN_ERR (svn_fs_revision_prop (&raw_value, c->fs, c->rev_id,
                                   prop_name, pool));

  *prop_value = raw_value;

  return SVN_NO_ERROR;
}


static svn_error_t *
get_root (svn_fs_root_t **root,
          svnlook_ctxt_t *c,
          apr_pool_t *pool)
{
  /* Open up the appropriate root (revision or transaction). */
  if (c->is_revision)
    {
      /* If we didn't get a valid revision number, we'll look at the
         youngest revision. */
      if (! SVN_IS_VALID_REVNUM (c->rev_id))
        SVN_ERR (svn_fs_youngest_rev (&(c->rev_id), c->fs, pool));

      SVN_ERR (svn_fs_revision_root (root, c->fs, c->rev_id, pool));
    }
  else
    {
      SVN_ERR (svn_fs_txn_root (root, c->txn, pool));
    }

  return SVN_NO_ERROR;
}



/*** Tree Routines ***/

/* Generate a generic delta tree. */
static svn_error_t *
generate_delta_tree (svn_repos_node_t **tree,
                     svn_repos_t *repos,
                     svn_fs_root_t *root, 
                     svn_revnum_t base_rev, 
                     svn_boolean_t use_copy_history,
                     apr_pool_t *pool)
{
  svn_fs_root_t *base_root;
  const svn_delta_editor_t *editor;
  void *edit_baton;
  apr_pool_t *edit_pool = svn_pool_create (pool);
  svn_fs_t *fs = svn_repos_fs (repos);

  /* Get the base root. */
  SVN_ERR (svn_fs_revision_root (&base_root, fs, base_rev, pool));

  /* Request our editor. */
  SVN_ERR (svn_repos_node_editor (&editor, &edit_baton, repos,
                                  base_root, root, pool, edit_pool));

  /* Drive our editor. */
  SVN_ERR (svn_repos_replay (root, editor, edit_baton, edit_pool));

  /* Return the tree we just built. */
  *tree = svn_repos_node_from_baton (edit_baton);
  svn_pool_destroy (edit_pool);
  return SVN_NO_ERROR;
}



/*** Tree Printing Routines ***/

/* Recursively print only directory nodes that either a) have property
   mods, or b) contains files that have changed. */
static svn_error_t *
print_dirs_changed_tree (svn_repos_node_t *node,
                         const char *path /* UTF-8! */,
                         apr_pool_t *pool)
{
  svn_repos_node_t *tmp_node;
  int print_me = 0;
  const char *full_path;
  apr_pool_t *subpool;

  SVN_ERR (check_cancel (NULL));

  if (! node)
    return SVN_NO_ERROR;

  /* Not a directory?  We're not interested. */
  if (node->kind != svn_node_dir)
    return SVN_NO_ERROR;

  /* Got prop mods?  Excellent. */
  if (node->prop_mod)
    print_me = 1;

  if (! print_me)
    {
      /* Fly through the list of children, checking for modified files. */
      tmp_node = node->child;
      if (tmp_node)
        {
          if ((tmp_node->kind == svn_node_file)
              || (tmp_node->text_mod)
              || (tmp_node->action == 'A')
              || (tmp_node->action == 'D'))
            {
              print_me = 1;
            }
          while (tmp_node->sibling && (! print_me ))
            {
              tmp_node = tmp_node->sibling;
              if ((tmp_node->kind == svn_node_file)
                  || (tmp_node->text_mod)
                  || (tmp_node->action == 'A')
                  || (tmp_node->action == 'D'))
                {
                  print_me = 1;
                }
            }
        }
    }
  
  /* Print the node if it qualifies. */
  if (print_me)
    {
      SVN_ERR (svn_cmdline_printf (pool, "%s/\n", path));
    }

⌨️ 快捷键说明

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