📄 log-cmd.c
字号:
/*
* log-cmd.c -- Display log messages
*
* ====================================================================
* 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. ***/
#define APR_WANT_STRFUNC
#define APR_WANT_STDIO
#include <apr_want.h>
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_string.h"
#include "svn_path.h"
#include "svn_delta.h"
#include "svn_error.h"
#include "svn_pools.h"
#include "svn_sorts.h"
#include "svn_xml.h"
#include "svn_time.h"
#include "svn_cmdline.h"
#include "svn_subst.h"
#include "cl.h"
#include "svn_private_config.h"
/*** Code. ***/
/* Helper for log_message_receiver().
*
* Return the number of lines in MSG, allowing any kind of newline
* termination (CR, CRLF, or LFCR), even inconsistent. The minimum
* number of lines in MSG is 1 -- even the empty string is considered
* to have one line, due to the way we print log messages.
*/
static int
num_lines (const char *msg)
{
int count = 1;
const char *p;
for (p = msg; *p; p++)
{
if (*p == '\n')
{
count++;
if (*(p + 1) == '\r')
p++;
}
else if (*p == '\r')
{
count++;
if (*(p + 1) == '\n')
p++;
}
}
return count;
}
static svn_error_t *
error_checked_fputs(const char *string, FILE* stream)
{
/* This function is equal to svn_cmdline_fputs() minus
the utf8->local encoding translation */
/* On POSIX systems, errno will be set on an error in fputs, but this might
not be the case on other platforms. We reset errno and only
use it if it was set by the below fputs call. Else, we just return
a generic error. */
errno = 0;
if (fputs (string, stream) == EOF)
{
if (errno)
return svn_error_wrap_apr (errno, _("Write error"));
else
return svn_error_create (SVN_ERR_IO_WRITE_ERROR, NULL, NULL);
}
return SVN_NO_ERROR;
}
/* Baton for log_message_receiver() and log_message_receiver_xml(). */
struct log_receiver_baton
{
/* Check for cancellation on each invocation of a log receiver. */
svn_cancel_func_t cancel_func;
void *cancel_baton;
/* Don't print log message body nor its line count. */
svn_boolean_t omit_log_message;
};
/* The separator between log messages. */
#define SEP_STRING \
"------------------------------------------------------------------------\n"
/* Implement `svn_log_message_receiver_t', printing the logs in
* a human-readable and machine-parseable format.
*
* BATON is of type `struct log_receiver_baton'.
*
* First, print a header line. Then if CHANGED_PATHS is non-null,
* print all affected paths in a list headed "Changed paths:\n",
* immediately following the header line. Then print a newline
* followed by the message body, unless BATON->omit_log_message is true.
*
* Here are some examples of the output:
*
* $ svn log -r1847:1846
* ------------------------------------------------------------------------
* rev 1847: cmpilato | Wed 1 May 2002 15:44:26 | 7 lines
*
* Fix for Issue #694.
*
* * subversion/libsvn_repos/delta.c
* (delta_files): Rework the logic in this function to only call
* send_text_deltas if there are deltas to send, and within that case,
* only use a real delta stream if the caller wants real text deltas.
*
* ------------------------------------------------------------------------
* rev 1846: whoever | Wed 1 May 2002 15:23:41 | 1 line
*
* imagine an example log message here
* ------------------------------------------------------------------------
*
* Or:
*
* $ svn log -r1847:1846 -v
* ------------------------------------------------------------------------
* rev 1847: cmpilato | Wed 1 May 2002 15:44:26 | 7 lines
* Changed paths:
* M /trunk/subversion/libsvn_repos/delta.c
*
* Fix for Issue #694.
*
* * subversion/libsvn_repos/delta.c
* (delta_files): Rework the logic in this function to only call
* send_text_deltas if there are deltas to send, and within that case,
* only use a real delta stream if the caller wants real text deltas.
*
* ------------------------------------------------------------------------
* rev 1846: whoever | Wed 1 May 2002 15:23:41 | 1 line
* Changed paths:
* M /trunk/notes/fs_dumprestore.txt
* M /trunk/subversion/libsvn_repos/dump.c
*
* imagine an example log message here
* ------------------------------------------------------------------------
*
* Or:
*
* $ svn log -r1847:1846 -q
* ------------------------------------------------------------------------
* rev 1847: cmpilato | Wed 1 May 2002 15:44:26
* ------------------------------------------------------------------------
* rev 1846: whoever | Wed 1 May 2002 15:23:41
* ------------------------------------------------------------------------
*
* Or:
*
* $ svn log -r1847:1846 -qv
* ------------------------------------------------------------------------
* rev 1847: cmpilato | Wed 1 May 2002 15:44:26
* Changed paths:
* M /trunk/subversion/libsvn_repos/delta.c
* ------------------------------------------------------------------------
* rev 1846: whoever | Wed 1 May 2002 15:23:41
* Changed paths:
* M /trunk/notes/fs_dumprestore.txt
* M /trunk/subversion/libsvn_repos/dump.c
* ------------------------------------------------------------------------
*
*/
static svn_error_t *
log_message_receiver (void *baton,
apr_hash_t *changed_paths,
svn_revnum_t rev,
const char *author,
const char *date,
const char *msg,
apr_pool_t *pool)
{
struct log_receiver_baton *lb = baton;
/* Number of lines in the msg. */
int lines;
if (lb->cancel_func)
SVN_ERR (lb->cancel_func (lb->cancel_baton));
if (rev == 0)
return svn_cmdline_printf (pool, _("No commit for revision 0.\n"));
/* ### See http://subversion.tigris.org/issues/show_bug.cgi?id=807
for more on the fallback fuzzy conversions below. */
if (author == NULL)
author = _("(no author)");
if (date && date[0])
{
/* Convert date to a format for humans. */
apr_time_t time_temp;
SVN_ERR (svn_time_from_cstring (&time_temp, date, pool));
date = svn_time_to_human_cstring(time_temp, pool);
}
else
date = _("(no date)");
if (! lb->omit_log_message && msg == NULL)
msg = "";
SVN_ERR (svn_cmdline_printf (pool,
SEP_STRING "r%ld | %s | %s",
rev, author, date));
if (! lb->omit_log_message)
{
lines = num_lines (msg);
/*### FIXME: how do we translate this without ngettext?! */
SVN_ERR (svn_cmdline_printf (pool,
" | %d line%s", lines,
(lines > 1) ? "s" : ""));
}
SVN_ERR (svn_cmdline_printf (pool, "\n"));
if (changed_paths)
{
apr_array_header_t *sorted_paths;
int i;
/* Get an array of sorted hash keys. */
sorted_paths = svn_sort__hash (changed_paths,
svn_sort_compare_items_as_paths, pool);
SVN_ERR (svn_cmdline_printf (pool,
_("Changed paths:\n")));
for (i = 0; i < sorted_paths->nelts; i++)
{
svn_sort__item_t *item = &(APR_ARRAY_IDX (sorted_paths, i,
svn_sort__item_t));
const char *path = item->key;
svn_log_changed_path_t *log_item
= apr_hash_get (changed_paths, item->key, item->klen);
const char *copy_data = "";
if (log_item->copyfrom_path
&& SVN_IS_VALID_REVNUM (log_item->copyfrom_rev))
{
copy_data
= apr_psprintf (pool,
_(" (from %s:%ld)"),
log_item->copyfrom_path,
log_item->copyfrom_rev);
}
SVN_ERR (svn_cmdline_printf (pool, " %c %s%s\n",
log_item->action, path,
copy_data));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -