📄 util.c
字号:
apr_hash_t *config,
apr_pool_t *pool)
{
struct log_msg_baton *lmb = apr_palloc (pool, sizeof (*lmb));
if (opt_state->filedata)
{
if (strlen (opt_state->filedata->data) < opt_state->filedata->len)
{
/* The data contains a zero byte, and therefore can't be
represented as a C string. Punt now; it's probably not
a deliberate encoding, and even if it is, we still
can't handle it. */
return svn_error_create (SVN_ERR_CL_BAD_LOG_MESSAGE, NULL,
_("Log message contains a zero byte"));
}
lmb->message = opt_state->filedata->data;
}
else
{
lmb->message = opt_state->message;
}
lmb->editor_cmd = opt_state->editor_cmd;
if (opt_state->encoding)
{
lmb->message_encoding = opt_state->encoding;
}
else if (config)
{
svn_config_t *cfg = apr_hash_get (config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING);
svn_config_get (cfg, &(lmb->message_encoding),
SVN_CONFIG_SECTION_MISCELLANY,
SVN_CONFIG_OPTION_LOG_ENCODING,
NULL);
}
lmb->base_dir = base_dir ? base_dir : "";
lmb->tmpfile_left = NULL;
lmb->config = config;
lmb->pool = pool;
*baton = lmb;
return SVN_NO_ERROR;
}
svn_error_t *
svn_cl__cleanup_log_msg (void *log_msg_baton,
svn_error_t *commit_err)
{
struct log_msg_baton *lmb = log_msg_baton;
/* If there was no tmpfile left, or there is no log message baton,
return COMMIT_ERR. */
if ((! lmb) || (! lmb->tmpfile_left))
return commit_err;
/* If there was no commit error, cleanup the tmpfile and return. */
if (! commit_err)
return svn_io_remove_file (lmb->tmpfile_left, lmb->pool);
/* There was a commit error; there is a tmpfile. Leave the tmpfile
around, and add message about its presence to the commit error
chain. Then return COMMIT_ERR. If the conversion from UTF-8 to
native encoding fails, we have to compose that error with the
commit error chain, too. */
svn_error_compose
(commit_err,
svn_error_create (commit_err->apr_err,
svn_error_createf (commit_err->apr_err, NULL,
" '%s'", lmb->tmpfile_left),
_("Your commit message was left in "
"a temporary file:")));
return commit_err;
}
/* Remove line-starting PREFIX and everything after it from BUFFER.
If NEW_LEN is non-NULL, return the new length of BUFFER in
*NEW_LEN. */
static void
truncate_buffer_at_prefix (apr_size_t *new_len,
char *buffer,
const char *prefix)
{
char *substring = buffer;
assert (buffer && prefix);
/* Initialize *NEW_LEN. */
if (new_len)
*new_len = strlen (buffer);
while (1)
{
/* Find PREFIX in BUFFER. */
substring = strstr (substring, prefix);
if (! substring)
return;
/* We found PREFIX. Is it really a PREFIX? Well, if it's the first
thing in the file, or if the character before it is a
line-terminator character, it sure is. */
if ((substring == buffer)
|| (*(substring - 1) == '\r')
|| (*(substring - 1) == '\n'))
{
*substring = '\0';
if (new_len)
*new_len = substring - buffer;
}
else if (substring)
{
/* Well, it wasn't really a prefix, so just advance by 1
character and continue. */
substring++;
}
}
return;
}
#define EDITOR_EOF_PREFIX _("--This line, and those below, will be ignored--")
/* This function is of type svn_client_get_commit_log_t. */
svn_error_t *
svn_cl__get_log_message (const char **log_msg,
const char **tmp_file,
apr_array_header_t *commit_items,
void *baton,
apr_pool_t *pool)
{
svn_stringbuf_t *default_msg = NULL;
struct log_msg_baton *lmb = baton;
svn_stringbuf_t *message = NULL;
/* Set default message. */
default_msg = svn_stringbuf_create(APR_EOL_STR, pool);
svn_stringbuf_appendcstr(default_msg, EDITOR_EOF_PREFIX);
svn_stringbuf_appendcstr(default_msg, APR_EOL_STR APR_EOL_STR);
*tmp_file = NULL;
if (lmb->message)
{
svn_string_t *log_msg_string = svn_string_create ("", pool);
log_msg_string->data = lmb->message;
log_msg_string->len = strlen (lmb->message);
SVN_ERR (svn_subst_translate_string (&log_msg_string, log_msg_string,
lmb->message_encoding, pool));
*log_msg = log_msg_string->data;
/* Trim incoming messages the EOF marker text and the junk that
follows it. */
truncate_buffer_at_prefix (NULL, (char*)*log_msg, EDITOR_EOF_PREFIX);
return SVN_NO_ERROR;
}
if (! (commit_items || commit_items->nelts))
{
*log_msg = "";
return SVN_NO_ERROR;
}
while (! message)
{
/* We still don't have a valid commit message. Use $EDITOR to
get one. Note that svn_cl__edit_externally will still return
a UTF-8'ized log message. */
int i;
svn_stringbuf_t *tmp_message = svn_stringbuf_dup (default_msg, pool);
svn_error_t *err = SVN_NO_ERROR;
svn_string_t *msg_string = svn_string_create ("", pool);
for (i = 0; i < commit_items->nelts; i++)
{
svn_client_commit_item_t *item
= ((svn_client_commit_item_t **) commit_items->elts)[i];
const char *path = item->path;
char text_mod = '_', prop_mod = ' ';
if (! path)
path = item->url;
else if (! *path)
path = ".";
if (path && lmb->base_dir)
path = svn_path_is_child (lmb->base_dir, path, pool);
/* If still no path, then just use current directory. */
if (! path)
path = ".";
if ((item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
&& (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
text_mod = 'R';
else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
text_mod = 'A';
else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
text_mod = 'D';
else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_TEXT_MODS)
text_mod = 'M';
if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_PROP_MODS)
prop_mod = 'M';
svn_stringbuf_appendbytes (tmp_message, &text_mod, 1);
svn_stringbuf_appendbytes (tmp_message, &prop_mod, 1);
svn_stringbuf_appendcstr (tmp_message, " ");
svn_stringbuf_appendcstr (tmp_message, path);
svn_stringbuf_appendcstr (tmp_message, APR_EOL_STR);
}
msg_string->data = tmp_message->data;
msg_string->len = tmp_message->len;
/* Use the external edit to get a log message. */
err = svn_cl__edit_externally (&msg_string, &lmb->tmpfile_left,
lmb->editor_cmd, lmb->base_dir,
msg_string, "svn-commit",
lmb->config, TRUE, NULL, pool);
/* Dup the tmpfile path into its baton's pool. */
*tmp_file = lmb->tmpfile_left = apr_pstrdup (lmb->pool,
lmb->tmpfile_left);
/* If the edit returned an error, handle it. */
if (err)
{
if (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR)
err = svn_error_quick_wrap
(err, _("Could not use external editor to fetch log message; "
"consider setting the $SVN_EDITOR environment variable "
"or using the --message (-m) or --file (-F) options"));
return err;
}
if (msg_string)
message = svn_stringbuf_create_from_string (msg_string, pool);
/* Strip the prefix from the buffer. */
if (message)
truncate_buffer_at_prefix (&message->len, message->data,
EDITOR_EOF_PREFIX);
if (message)
{
/* We did get message, now check if it is anything more than just
white space as we will consider white space only as empty */
int len;
for (len = message->len - 1; len >= 0; len--)
{
/* FIXME: should really use an UTF-8 whitespace test
rather than apr_isspace, which is locale dependant */
if (! apr_isspace (message->data[len]))
break;
}
if (len < 0)
message = NULL;
}
if (! message)
{
const char *reply;
svn_cl__prompt_user (&reply,
_("\nLog message unchanged or not specified\n"
"a)bort, c)ontinue, e)dit\n"), pool);
if (reply)
{
char letter = apr_tolower (reply[0]);
/* If the user chooses to abort, we cleanup the
temporary file and exit the loop with a NULL
message. */
if ('a' == letter)
{
SVN_ERR (svn_io_remove_file (lmb->tmpfile_left, pool));
*tmp_file = lmb->tmpfile_left = NULL;
break;
}
/* If the user chooses to continue, we make an empty
message, which will cause us to exit the loop. We
also cleanup the temporary file. */
if ('c' == letter)
{
SVN_ERR (svn_io_remove_file (lmb->tmpfile_left, pool));
*tmp_file = lmb->tmpfile_left = NULL;
message = svn_stringbuf_create ("", pool);
}
/* If the user chooses anything else, the loop will
continue on the NULL message. */
}
}
}
*log_msg = message ? message->data : NULL;
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -