📄 main.c
字号:
/* * main.c: Subversion server inspection tool. * * ==================================================================== * Copyright (c) 2000-2006 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_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_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_lock, 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, svnlook__no_diff_added, svnlook__diff_copy_from, svnlook__revprop_opt, svnlook__full_paths, svnlook__copy_info };/* * 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 program 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")}, {"no-diff-added", svnlook__no_diff_added, 0, N_("do not print differences for added files")}, {"diff-copy-from", svnlook__diff_copy_from, 0, N_("print differences against the copy source")}, {"revprop", svnlook__revprop_opt, 0, N_("operate on a revision property (use with -r or -t)")}, {"full-paths", svnlook__full_paths, 0, N_("show full paths instead of indenting them")}, {"copy-info", svnlook__copy_info, 0, N_("show details for copies")}, {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', svnlook__copy_info} }, {"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, svnlook__no_diff_added, svnlook__diff_copy_from} }, {"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"), {0} }, {"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'} }, {"lock", subcommand_lock, {0}, N_("usage: svnlook lock REPOS_PATH PATH_IN_REPOS\n\n" "If a lock exists on a path in the repository, describe it.\n"), {0} }, {"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" "With --revprop, prints the raw value of a revision property.\n"), {'r', 't', svnlook__revprop_opt} }, {"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, or\n" "with the --revprop option, revision properties.\n" "With -v, show the property values too.\n"), {'r', 't', 'v', svnlook__revprop_opt} }, {"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, svnlook__full_paths} }, {"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 no_diff_added; /* --no-diff-added */ svn_boolean_t diff_copy_from; /* --diff-copy-from */ svn_boolean_t verbose; /* --verbose */ svn_boolean_t revprop; /* --revprop */ svn_boolean_t full_paths; /* --full-paths */ svn_boolean_t copy_info; /* --copy-info */};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_boolean_t no_diff_added; svn_boolean_t diff_copy_from; svn_boolean_t full_paths; svn_boolean_t copy_info; 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 voidsignal_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_replay2(root, "", SVN_INVALID_REVNUM, FALSE, editor, edit_baton, NULL, NULL, 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')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -