📄 info-cmd.c
字号:
/*
* info-cmd.c -- Display information about a resource
*
* ====================================================================
* 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/.
* ====================================================================
*/
/* ==================================================================== */
/*** Includes. ***/
#include "svn_cmdline.h"
#include "svn_wc.h"
#include "svn_pools.h"
#include "svn_string.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_time.h"
#include "cl.h"
#include "svn_private_config.h"
/*** Code. ***/
static svn_error_t *
svn_cl__info_print_time (apr_time_t atime,
const char *desc,
apr_pool_t *pool)
{
const char *time_utf8;
time_utf8 = svn_time_to_human_cstring (atime, pool);
SVN_ERR (svn_cmdline_printf (pool, "%s: %s\n", desc, time_utf8));
return SVN_NO_ERROR;
}
static svn_error_t *
print_entry (const char *target,
const svn_wc_entry_t *entry,
apr_pool_t *pool)
{
svn_boolean_t text_conflict = FALSE, props_conflict = FALSE;
SVN_ERR (svn_cmdline_printf (pool, _("Path: %s\n"),
svn_path_local_style (target, pool)));
/* Note: we have to be paranoid about checking that these are
valid, since svn_wc_entry() doesn't fill them in if they
aren't in the entries file. */
if (entry->name && strcmp (entry->name, SVN_WC_ENTRY_THIS_DIR))
SVN_ERR (svn_cmdline_printf (pool, _("Name: %s\n"), entry->name));
if (entry->url)
SVN_ERR (svn_cmdline_printf (pool, _("URL: %s\n"), entry->url));
if (entry->repos)
SVN_ERR (svn_cmdline_printf (pool, _("Repository: %s\n"), entry->repos));
if (entry->uuid)
SVN_ERR (svn_cmdline_printf (pool, _("Repository UUID: %s\n"),
entry->uuid));
if (SVN_IS_VALID_REVNUM (entry->revision))
SVN_ERR (svn_cmdline_printf (pool, _("Revision: %ld\n"), entry->revision));
switch (entry->kind)
{
case svn_node_file:
SVN_ERR (svn_cmdline_printf (pool, _("Node Kind: file\n")));
{
const char *dir_name;
svn_path_split (target, &dir_name, NULL, pool);
SVN_ERR (svn_wc_conflicted_p (&text_conflict, &props_conflict,
dir_name, entry, pool));
}
break;
case svn_node_dir:
SVN_ERR (svn_cmdline_printf (pool, _("Node Kind: directory\n")));
SVN_ERR (svn_wc_conflicted_p (&text_conflict, &props_conflict,
target, entry, pool));
break;
case svn_node_none:
SVN_ERR (svn_cmdline_printf (pool, _("Node Kind: none\n")));
break;
case svn_node_unknown:
default:
SVN_ERR (svn_cmdline_printf (pool, _("Node Kind: unknown\n")));
break;
}
switch (entry->schedule)
{
case svn_wc_schedule_normal:
SVN_ERR (svn_cmdline_printf (pool, _("Schedule: normal\n")));
break;
case svn_wc_schedule_add:
SVN_ERR (svn_cmdline_printf (pool, _("Schedule: add\n")));
break;
case svn_wc_schedule_delete:
SVN_ERR (svn_cmdline_printf (pool, _("Schedule: delete\n")));
break;
case svn_wc_schedule_replace:
SVN_ERR (svn_cmdline_printf (pool, _("Schedule: replace\n")));
break;
default:
break;
}
if (entry->copied)
{
if (entry->copyfrom_url)
SVN_ERR (svn_cmdline_printf (pool, _("Copied From URL: %s\n"),
entry->copyfrom_url));
if (SVN_IS_VALID_REVNUM (entry->copyfrom_rev))
SVN_ERR (svn_cmdline_printf (pool, _("Copied From Rev: %ld\n"),
entry->copyfrom_rev));
}
if (entry->cmt_author)
SVN_ERR (svn_cmdline_printf (pool, _("Last Changed Author: %s\n"),
entry->cmt_author));
if (SVN_IS_VALID_REVNUM (entry->cmt_rev))
SVN_ERR (svn_cmdline_printf (pool, _("Last Changed Rev: %ld\n"),
entry->cmt_rev));
if (entry->cmt_date)
SVN_ERR (svn_cl__info_print_time (entry->cmt_date,
_("Last Changed Date"), pool));
if (entry->text_time)
SVN_ERR (svn_cl__info_print_time (entry->text_time,
_("Text Last Updated"), pool));
if (entry->prop_time)
SVN_ERR (svn_cl__info_print_time (entry->prop_time,
_("Properties Last Updated"), pool));
if (entry->checksum)
SVN_ERR (svn_cmdline_printf (pool, _("Checksum: %s\n"),
entry->checksum));
if (text_conflict && entry->conflict_old)
SVN_ERR (svn_cmdline_printf (pool, _("Conflict Previous Base File: %s\n"),
svn_path_local_style (entry->conflict_old,
pool)));
if (text_conflict && entry->conflict_wrk)
SVN_ERR (svn_cmdline_printf
(pool, _("Conflict Previous Working File: %s\n"),
svn_path_local_style (entry->conflict_wrk, pool)));
if (text_conflict && entry->conflict_new)
SVN_ERR (svn_cmdline_printf (pool, _("Conflict Current Base File: %s\n"),
svn_path_local_style (entry->conflict_new,
pool)));
if (props_conflict && entry->prejfile)
SVN_ERR (svn_cmdline_printf (pool, _("Conflict Properties File: %s\n"),
svn_path_local_style (entry->prejfile,
pool)));
/* Print extra newline separator. */
SVN_ERR (svn_cmdline_printf (pool, "\n"));
return SVN_NO_ERROR;
}
static svn_error_t *
info_found_entry_callback (const char *path,
const svn_wc_entry_t *entry,
void *walk_baton,
apr_pool_t *pool)
{
/* We're going to receive dirents twice; we want to ignore the
first one (where it's a child of a parent dir), and only print
the second one (where we're looking at THIS_DIR.) */
if ((entry->kind == svn_node_dir)
&& (strcmp (entry->name, SVN_WC_ENTRY_THIS_DIR)))
return SVN_NO_ERROR;
return print_entry (path, entry, pool);
}
static const svn_wc_entry_callbacks_t
entry_walk_callbacks =
{
info_found_entry_callback
};
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__info (apr_getopt_t *os,
void *baton,
apr_pool_t *pool)
{
svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
apr_array_header_t *targets;
apr_pool_t *subpool = svn_pool_create (pool);
int i;
SVN_ERR (svn_opt_args_to_target_array (&targets, os,
opt_state->targets,
&(opt_state->start_revision),
&(opt_state->end_revision),
FALSE, pool));
/* Add "." if user passed 0 arguments. */
svn_opt_push_implicit_dot_target (targets, pool);
for (i = 0; i < targets->nelts; i++)
{
const char *target = ((const char **) (targets->elts))[i];
svn_wc_adm_access_t *adm_access;
const svn_wc_entry_t *entry;
svn_pool_clear (subpool);
/* Make sure the user hasn't passed a URL by mistake. */
if (svn_path_is_url (target))
return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("'svn info' only works on working copy paths, not URLs"));
SVN_ERR (svn_cl__check_cancel (ctx->cancel_baton));
SVN_ERR (svn_wc_adm_probe_open2 (&adm_access, NULL, target, FALSE,
opt_state->recursive ? -1 : 0,
subpool));
SVN_ERR (svn_wc_entry (&entry, target, adm_access, FALSE, subpool));
if (! entry)
{
/* Print non-versioned message and extra newline separator. */
SVN_ERR (svn_cmdline_printf
(subpool, _("%s: (Not a versioned resource)\n\n"),
svn_path_local_style (target, pool)));
continue;
}
if (entry->kind == svn_node_file)
SVN_ERR (print_entry (target, entry, subpool));
else if (entry->kind == svn_node_dir)
{
if (opt_state->recursive)
/* the generic entry-walker: */
SVN_ERR (svn_wc_walk_entries (target, adm_access,
&entry_walk_callbacks, NULL,
FALSE, pool));
else
SVN_ERR (print_entry (target, entry, subpool));
}
}
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -