* mu mv updates:
- rename --printtarget into --print-target - support 'delta' flags - add --ignore-dups to silently ignore the src = target case
This commit is contained in:
31
src/mu-cmd.c
31
src/mu-cmd.c
@ -285,19 +285,31 @@ mu_cmd_mkdir (MuConfig *opts)
|
||||
static gboolean
|
||||
mv_check_params (MuConfig *opts, MuFlags *flags)
|
||||
{
|
||||
if (!opts->params[1] || !opts->params[2]) {
|
||||
if (!opts->params[1]) {
|
||||
g_warning ("usage: mu mv [--flags=<flags>] <mailfile> "
|
||||
"<maildir>");
|
||||
"[<maildir>]");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: check for invalid flags */
|
||||
if (!opts->flagstr)
|
||||
*flags = MU_FLAG_INVALID; /* ie., ignore flags */
|
||||
else
|
||||
*flags = mu_flags_from_str (opts->flagstr,
|
||||
MU_FLAG_TYPE_MAILDIR |
|
||||
MU_FLAG_TYPE_MAILFILE);
|
||||
else {
|
||||
/* if there's a '+' or '-' sign in the string, it must
|
||||
* be a flag-delta */
|
||||
if (strstr (opts->flagstr, "+") || strstr (opts->flagstr, "-")) {
|
||||
MuFlags oldflags;
|
||||
oldflags = mu_maildir_get_flags_from_path (opts->params[1]);
|
||||
*flags = mu_flags_from_str_delta (opts->flagstr,
|
||||
oldflags,
|
||||
MU_FLAG_TYPE_MAILDIR|
|
||||
MU_FLAG_TYPE_MAILFILE);
|
||||
} else
|
||||
*flags = mu_flags_from_str (opts->flagstr,
|
||||
MU_FLAG_TYPE_MAILDIR |
|
||||
MU_FLAG_TYPE_MAILFILE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -310,7 +322,7 @@ cmd_mv_dev_null (MuConfig *opts)
|
||||
return MU_ERROR_FILE;
|
||||
}
|
||||
|
||||
if (opts->printtarget)
|
||||
if (opts->print_target)
|
||||
g_print ("/dev/null\n"); /* /dev/null */
|
||||
|
||||
return MU_OK;
|
||||
@ -334,7 +346,8 @@ mu_cmd_mv (MuConfig *opts)
|
||||
err = NULL;
|
||||
fullpath = mu_maildir_move_message (opts->params[1],
|
||||
opts->params[2],
|
||||
flags, &err);
|
||||
flags, opts->ignore_dups,
|
||||
&err);
|
||||
if (!fullpath) {
|
||||
if (err) {
|
||||
MuError code;
|
||||
@ -346,7 +359,7 @@ mu_cmd_mv (MuConfig *opts)
|
||||
return MU_ERROR_FILE;
|
||||
|
||||
} else {
|
||||
if (opts->printtarget)
|
||||
if (opts->print_target)
|
||||
g_print ("%s\n", fullpath);
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
@ -322,7 +322,10 @@ config_options_group_mv (MuConfig *opts)
|
||||
GOptionEntry entries[] = {
|
||||
{"flags", 0, 0, G_OPTION_ARG_STRING, &opts->flagstr,
|
||||
"flags to set for the target (DFNPRST)", NULL},
|
||||
{"printtarget", 0, 0, G_OPTION_ARG_NONE, &opts->printtarget,
|
||||
{"ignore-dups", 0, 0, G_OPTION_ARG_NONE, &opts->ignore_dups,
|
||||
"whether to silently ignore the source = target case",
|
||||
NULL},
|
||||
{"print-target", 0, 0, G_OPTION_ARG_NONE, &opts->print_target,
|
||||
"whether to print the target path upon succesful completion",
|
||||
NULL},
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
|
||||
@ -128,10 +128,11 @@ struct _MuConfig {
|
||||
/* options for mv */
|
||||
char *flagstr; /* message flags to set for
|
||||
* the target */
|
||||
gboolean printtarget; /* should be print the
|
||||
* target file path on
|
||||
* stdout */
|
||||
|
||||
gboolean print_target; /* should be print the
|
||||
* target file path on
|
||||
* stdout */
|
||||
gboolean ignore_dups; /* silently ignore the
|
||||
* src=target case */
|
||||
/* options for view */
|
||||
gboolean terminator; /* add separator \f between
|
||||
* multiple messages in mu
|
||||
|
||||
@ -60,7 +60,6 @@ mu_flag_type (MuFlags flag)
|
||||
if (flag >= MU_FLAG_SIGNED && flag <= MU_FLAG_HAS_ATTACH)
|
||||
return MU_FLAG_TYPE_CONTENT;
|
||||
|
||||
g_return_val_if_reached (MU_FLAG_TYPE_INVALID);
|
||||
return MU_FLAG_TYPE_INVALID;
|
||||
}
|
||||
|
||||
@ -87,7 +86,6 @@ mu_flag_char (MuFlags flag)
|
||||
case MU_FLAG_UNREAD: return 'u';
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -115,13 +113,11 @@ mu_flag_from_char (char kar)
|
||||
case 'u': return MU_FLAG_UNREAD;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (MU_FLAG_INVALID);
|
||||
return MU_FLAG_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* does not use FLAG_INFO, optimized */
|
||||
const char*
|
||||
mu_flag_name (MuFlags flag)
|
||||
@ -143,7 +139,6 @@ mu_flag_name (MuFlags flag)
|
||||
case MU_FLAG_UNREAD: return "unread";
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -160,7 +155,7 @@ mu_flags_to_str_s (MuFlags flags, MuFlagType types)
|
||||
types & FLAG_INFO[u].flag_type)
|
||||
str[v++] = FLAG_INFO[u].kar;
|
||||
str[v] = '\0';
|
||||
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -199,3 +194,39 @@ mu_flags_foreach (MuFlagsForeachFunc func, gpointer user_data)
|
||||
func (FLAG_INFO[u].flag, user_data);
|
||||
}
|
||||
|
||||
|
||||
MuFlags
|
||||
mu_flags_from_str_delta (const char *str, MuFlags oldflags,
|
||||
MuFlagType types)
|
||||
{
|
||||
const char *cur;
|
||||
MuFlags newflags;
|
||||
|
||||
g_return_val_if_fail (str, MU_FLAG_INVALID);
|
||||
|
||||
for (cur = str, newflags = oldflags; *cur; ++cur) {
|
||||
|
||||
MuFlags f;
|
||||
if (*cur == '+' || *cur == '-') {
|
||||
f = mu_flag_from_char (cur[1]);
|
||||
if (f == 0)
|
||||
goto error;
|
||||
if (*cur == '+')
|
||||
newflags |= f;
|
||||
else
|
||||
newflags &= ~f;
|
||||
++cur;
|
||||
continue;
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
return newflags;
|
||||
error:
|
||||
g_warning ("invalid flag string");
|
||||
return MU_FLAG_INVALID;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -122,6 +122,26 @@ const char* mu_flags_to_str_s (MuFlags flags, MuFlagType types);
|
||||
MuFlags mu_flags_from_str (const char *str, MuFlagType types);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update #oldflags with the flags in #str, where #str consists of the
|
||||
* the normal flag characters, but prefixed with either '+' or '-',
|
||||
* which means resp. "add this flag" or "remove this flag" from
|
||||
* oldflags. So, e.g. "-N+S" would unset the NEW flag and set the
|
||||
* SEEN flag, without affecting other flags.
|
||||
*
|
||||
* @param str the string representation
|
||||
* @param old flags to update
|
||||
* @param types the flag types to accept (other will be ignored)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
MuFlags mu_flags_from_str_delta (const char *str, MuFlags oldflags,
|
||||
MuFlagType types);
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void (*MuFlagsForeachFunc) (MuFlags flag, gpointer user_data);
|
||||
|
||||
/**
|
||||
|
||||
@ -812,10 +812,12 @@ msg_move (const char* src, const char *dst, GError **err)
|
||||
|
||||
gchar*
|
||||
mu_maildir_move_message (const char* oldpath, const char* targetmdir,
|
||||
MuFlags newflags, GError **err)
|
||||
MuFlags newflags, gboolean ignore_dups,
|
||||
GError **err)
|
||||
{
|
||||
char *newfullpath;
|
||||
gboolean rv;
|
||||
gboolean src_is_target;
|
||||
|
||||
g_return_val_if_fail (oldpath, FALSE);
|
||||
|
||||
@ -827,16 +829,21 @@ mu_maildir_move_message (const char* oldpath, const char* targetmdir,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (oldpath, newfullpath) == 0) {
|
||||
|
||||
src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0);
|
||||
|
||||
if (!ignore_dups && src_is_target) {
|
||||
g_set_error (err, 0, MU_ERROR_FILE_TARGET_EQUALS_SOURCE,
|
||||
"target equals source");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rv = msg_move (oldpath, newfullpath, err);
|
||||
if (!rv) {
|
||||
g_free (newfullpath);
|
||||
return NULL;
|
||||
if (!src_is_target) {
|
||||
rv = msg_move (oldpath, newfullpath, err);
|
||||
if (!rv) {
|
||||
g_free (newfullpath);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return newfullpath;
|
||||
|
||||
@ -171,14 +171,17 @@ char* mu_maildir_get_new_path (const char *oldpath, const char *new_mdir,
|
||||
* of the message are affected; note that this may still involve a
|
||||
* moved to another directory (say, from new/ to cur/)
|
||||
* @param flags to set for the target (influences the filename, path)
|
||||
* @param ignore_dups whether to silent ignore the src=target case (and return TRUE)
|
||||
* @param err (may be NULL) may contain error information; note if the
|
||||
* function return FALSE, err is not set for all error condition
|
||||
* (ie. not for parameter errors)
|
||||
*
|
||||
* @return return the full path name of the target file (g_free) if
|
||||
* the move succeeded, NULL otherwise
|
||||
*/
|
||||
gchar* mu_maildir_move_message (const char* oldpath, const char* targetmdir,
|
||||
MuFlags newflags, GError **err);
|
||||
MuFlags newflags, gboolean ignore_dups,
|
||||
GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
Reference in New Issue
Block a user