mu-move: add new move sub command
Add sub-command to move messages; add tests and docs. Fixes #157
This commit is contained in:
@ -26,6 +26,7 @@ mu = executable(
|
||||
'mu-cmd-init.cc',
|
||||
'mu-cmd-index.cc',
|
||||
'mu-cmd-mkdir.cc',
|
||||
'mu-cmd-move.cc',
|
||||
'mu-cmd-remove.cc',
|
||||
'mu-cmd-script.cc',
|
||||
'mu-cmd-server.cc',
|
||||
@ -76,6 +77,13 @@ test('test-cmd-mkdir',
|
||||
cpp_args: ['-DBUILD_TESTS'],
|
||||
dependencies: [glib_dep, lib_mu_dep]))
|
||||
|
||||
test('test-cmd-move',
|
||||
executable('test-cmd-move',
|
||||
'mu-cmd-move.cc',
|
||||
install: false,
|
||||
cpp_args: ['-DBUILD_TESTS'],
|
||||
dependencies: [glib_dep, lib_mu_dep]))
|
||||
|
||||
test('test-cmd-remove',
|
||||
executable('test-cmd-remove',
|
||||
'mu-cmd-remove.cc',
|
||||
|
||||
276
mu/mu-cmd-move.cc
Normal file
276
mu/mu-cmd-move.cc
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
** Copyright (C) 2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
** Free Software Foundation; either version 3, or (at your option) any
|
||||
** later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "mu-cmd.hh"
|
||||
|
||||
#include "mu-store.hh"
|
||||
#include "mu-maildir.hh"
|
||||
#include "message/mu-message-file.hh"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace Mu;
|
||||
|
||||
|
||||
Result<void>
|
||||
Mu::mu_cmd_move(Mu::Store& store, const Options& opts)
|
||||
{
|
||||
const auto& src{opts.move.src};
|
||||
if (::access(src.c_str(), R_OK) != 0 || determine_dtype(src) != DT_REG)
|
||||
return Err(Error::Code::InvalidArgument,
|
||||
"Source is not a readable file");
|
||||
|
||||
auto id{store.find_message_id(src)};
|
||||
if (!id)
|
||||
return Err(Error{Error::Code::InvalidArgument,
|
||||
"Source file is not present in database"}
|
||||
.add_hint("Perhaps run mu index?"));
|
||||
|
||||
std::string dest{opts.move.dest};
|
||||
Option<const std::string&> dest_path;
|
||||
if (dest.empty() && opts.move.flags.empty())
|
||||
return Err(Error::Code::InvalidArgument,
|
||||
"Must have at least one of destination and flags");
|
||||
else if (!dest.empty()) {
|
||||
const auto mdirs{store.maildirs()};
|
||||
mu_printerrln("XXXX");
|
||||
for (auto&& m:mdirs)
|
||||
mu_printerrln("m:'{}'", m);
|
||||
|
||||
if (!seq_some(mdirs, [&](auto &&d){ return d == dest;}))
|
||||
return Err(Error{Error::Code::InvalidArgument,
|
||||
"No maildir '{}' in store", dest}
|
||||
.add_hint("Try 'mu mkdir'"));
|
||||
else
|
||||
dest_path = dest;
|
||||
}
|
||||
|
||||
auto old_flags{flags_from_path(src)};
|
||||
if (!old_flags)
|
||||
return Err(Error::Code::InvalidArgument, "failed to determine old flags");
|
||||
|
||||
Flags new_flags;
|
||||
if (!opts.move.flags.empty()) {
|
||||
if (auto&& nflags{flags_from_expr(to_string_view(opts.move.flags),
|
||||
*old_flags)}; !nflags)
|
||||
return Err(Error::Code::InvalidArgument, "Invalid flags");
|
||||
else
|
||||
new_flags = flags_maildir_file(*nflags);
|
||||
|
||||
if (any_of(new_flags & Flags::New) && new_flags != Flags::New)
|
||||
return Err(Error{Error::Code::File,
|
||||
"the New flag cannot be combined with others"}
|
||||
.add_hint("See the mu-move manpage"));
|
||||
}
|
||||
|
||||
Store::MoveOptions move_opts{};
|
||||
if (opts.move.change_name)
|
||||
move_opts |= Store::MoveOptions::ChangeName;
|
||||
if (opts.move.update_dups)
|
||||
move_opts |= Store::MoveOptions::DupFlags;
|
||||
if (opts.move.dry_run)
|
||||
move_opts |= Store::MoveOptions::DryRun;
|
||||
|
||||
auto id_paths = store.move_message(*id, dest_path, new_flags, move_opts);
|
||||
if (!id_paths)
|
||||
return Err(std::move(id_paths.error()));
|
||||
|
||||
for (const auto&[_id, path]: *id_paths)
|
||||
mu_println("{}", path);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef BUILD_TESTS
|
||||
/*
|
||||
* Tests.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utils/mu-test-utils.hh"
|
||||
|
||||
static void
|
||||
test_move_dry_run()
|
||||
{
|
||||
allow_warnings();
|
||||
|
||||
TempDir tdir;
|
||||
const auto dbpath{runtime_path(RuntimePath::XapianDb, tdir.path())};
|
||||
|
||||
auto res = run_command0({CP_PROGRAM, "-r", MU_TESTMAILDIR, tdir.path()});
|
||||
assert_valid_command(res);
|
||||
|
||||
const auto testpath{join_paths(tdir.path(), "testdir")};
|
||||
const auto src{join_paths(testpath, "cur", "1220863042.12663_1.mindcrime!2,S")};
|
||||
{
|
||||
auto store = Store::make_new(dbpath, testpath, {});
|
||||
assert_valid_result(store);
|
||||
g_assert_true(store->indexer().start({}, true/*block*/));
|
||||
}
|
||||
|
||||
// make a message 'New'
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"--flags", "N", "--dry-run"});
|
||||
assert_valid_command(res);
|
||||
|
||||
auto dst{join_paths(testpath, "new", "1220863042.12663_1.mindcrime")};
|
||||
assert_equal(res->standard_out, dst + '\n');
|
||||
|
||||
g_assert_true(::access(dst.c_str(), F_OK) != 0);
|
||||
g_assert_true(::access(src.c_str(), F_OK) == 0);
|
||||
}
|
||||
|
||||
// change some flags
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"--flags", "FP", "--dry-run"});
|
||||
assert_valid_command(res);
|
||||
|
||||
auto dst{join_paths(testpath, "cur", "1220863042.12663_1.mindcrime!2,FP")};
|
||||
assert_equal(res->standard_out, dst + '\n');
|
||||
}
|
||||
|
||||
// change some relative flag
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"--flags", "+F", "--dry-run"});
|
||||
assert_valid_command(res);
|
||||
|
||||
auto dst{join_paths(testpath, "cur", "1220863042.12663_1.mindcrime!2,FS")};
|
||||
assert_equal(res->standard_out, dst + '\n');
|
||||
}
|
||||
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"--flags", "-S+P+T", "--dry-run"});
|
||||
assert_valid_command(res);
|
||||
|
||||
auto dst{join_paths(testpath, "cur", "1220863042.12663_1.mindcrime!2,PT")};
|
||||
assert_equal(res->standard_out, dst + '\n');
|
||||
}
|
||||
|
||||
// change maildir
|
||||
for (auto& o : {"o1", "o2"})
|
||||
assert_valid_result(maildir_mkdir(join_paths(tdir.path(), "testdir", o)));
|
||||
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"/o1", "--flags", "-S+F", "--dry-run"});
|
||||
assert_valid_command(res);
|
||||
assert_equal(res->standard_out,
|
||||
join_paths(testpath,
|
||||
"o1/cur", "1220863042.12663_1.mindcrime!2,F") + "\n");
|
||||
}
|
||||
|
||||
// change-dups; first create some dups and index them.
|
||||
assert_valid_result(run_command0({CP_PROGRAM, src, join_paths(testpath, "o1/cur")}));
|
||||
assert_valid_result(run_command0({CP_PROGRAM, src, join_paths(testpath, "o2/cur")}));
|
||||
{
|
||||
auto store = Store::make(dbpath, Store::Options::Writable);
|
||||
assert_valid_result(store);
|
||||
g_assert_true(store->indexer().start({}, true/*block*/));
|
||||
}
|
||||
|
||||
// change some flags + update dups
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"--flags", "-S+S+T+R", "--update-dups", "--dry-run"});
|
||||
assert_valid_command(res);
|
||||
|
||||
auto p{join_paths(testpath, "cur", "1220863042.12663_1.mindcrime!2,RST")};
|
||||
auto p1{join_paths(testpath, "o1", "cur", "1220863042.12663_1.mindcrime!2,RS")};
|
||||
auto p2{join_paths(testpath, "o2", "cur", "1220863042.12663_1.mindcrime!2,RS")};
|
||||
|
||||
assert_equal(res->standard_out, mu_format("{}\n{}\n{}\n", p, p1, p2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_move_real()
|
||||
{
|
||||
allow_warnings();
|
||||
|
||||
TempDir tdir;
|
||||
const auto dbpath{runtime_path(RuntimePath::XapianDb, tdir.path())};
|
||||
|
||||
auto res = run_command0({CP_PROGRAM, "-r", MU_TESTMAILDIR, tdir.path()});
|
||||
assert_valid_command(res);
|
||||
|
||||
const auto testpath{join_paths(tdir.path(), "testdir")};
|
||||
const auto src{join_paths(testpath, "cur", "1220863042.12663_1.mindcrime!2,S")};
|
||||
{
|
||||
auto store = Store::make_new(dbpath, testpath, {});
|
||||
assert_valid_result(res);
|
||||
g_assert_true(store->indexer().start({}, true/*block*/));
|
||||
}
|
||||
|
||||
{
|
||||
auto res = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src,
|
||||
"--flags", "N"});
|
||||
assert_valid_command(res);
|
||||
auto dst{join_paths(testpath, "new", "1220863042.12663_1.mindcrime")};
|
||||
g_assert_true(::access(dst.c_str(), F_OK) == 0);
|
||||
g_assert_true(::access(src.c_str(), F_OK) != 0);
|
||||
}
|
||||
|
||||
// change flags, maildir, update-dups
|
||||
// change-dups; first create some dups and index them.
|
||||
const auto src2{join_paths(testpath, "cur", "1305664394.2171_402.cthulhu!2,")};
|
||||
for (auto& o : {"o1", "o2", "o3"})
|
||||
assert_valid_result(maildir_mkdir(join_paths(tdir.path(), "testdir", o)));
|
||||
assert_valid_result(run_command0({CP_PROGRAM, src2, join_paths(testpath, "o1/cur")}));
|
||||
assert_valid_result(run_command0({CP_PROGRAM, src2, join_paths(testpath, "o2/new")}));
|
||||
{
|
||||
auto store = Store::make(dbpath, Store::Options::Writable);
|
||||
assert_valid_result(store);
|
||||
g_assert_true(store->indexer().start({}, true/*block*/));
|
||||
}
|
||||
|
||||
auto res2 = run_command0({MU_PROGRAM, "move", "--muhome", tdir.path(), src2, "/o3",
|
||||
"--flags", "-S+S+T+R", "--update-dups", "--change-name"});
|
||||
assert_valid_command(res2);
|
||||
|
||||
auto store = Store::make(dbpath, Store::Options::Writable);
|
||||
assert_valid_result(store);
|
||||
g_assert_true(store->indexer().start({}, true/*block*/));
|
||||
|
||||
for (auto&& f: split(res2->standard_out, "\n")) {
|
||||
//mu_println(">> {}", f);
|
||||
if (f.length() > 2)
|
||||
g_assert_true(::access(f.c_str(), F_OK) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
mu_test_init(&argc, &argv);
|
||||
|
||||
g_test_add_func("/cmd/move/dry-run", test_move_dry_run);
|
||||
g_test_add_func("/cmd/move/real", test_move_real);
|
||||
|
||||
return g_test_run();
|
||||
|
||||
}
|
||||
#endif /*BUILD_TESTS*/
|
||||
@ -140,6 +140,8 @@ Mu::mu_cmd_execute(const Options& opts) try {
|
||||
return with_writable_store(mu_cmd_add, opts);
|
||||
case Options::SubCommand::Remove:
|
||||
return with_writable_store(mu_cmd_remove, opts);
|
||||
case Options::SubCommand::Move:
|
||||
return with_writable_store(mu_cmd_move, opts);
|
||||
case Options::SubCommand::Index:
|
||||
return with_writable_store(mu_cmd_index, opts);
|
||||
|
||||
|
||||
@ -127,6 +127,15 @@ Result<void> mu_cmd_init(const Options& opts);
|
||||
*/
|
||||
Result<void> mu_cmd_mkdir(const Options& opts);
|
||||
|
||||
/**
|
||||
* execute the 'move' command
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return Ok() or some error
|
||||
*/
|
||||
Result<void> mu_cmd_move(Store& store, const Options& opts);
|
||||
|
||||
/**
|
||||
* execute the 'remove' command
|
||||
*
|
||||
|
||||
@ -197,6 +197,12 @@ static const std::function ExpandPath = [](std::string filepath)->std::string {
|
||||
return filepath = std::move(res.value());
|
||||
};
|
||||
|
||||
|
||||
// Canonicalize path
|
||||
static const std::function CanonicalizePath = [](std::string filepath)->std::string {
|
||||
return filepath = canonicalize_filename(filepath);
|
||||
};
|
||||
|
||||
/*
|
||||
* common
|
||||
*/
|
||||
@ -481,6 +487,31 @@ sub_mkdir(CLI::App& sub, Options& opts)
|
||||
->required();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sub_move(CLI::App& sub, Options& opts)
|
||||
{
|
||||
sub.add_flag("--change-name", opts.move.change_name,
|
||||
"Change name of target file");
|
||||
sub.add_flag("--update-dups", opts.move.update_dups,
|
||||
"Update duplicate messages too");
|
||||
sub.add_flag("--dry-run,-n", opts.move.dry_run,
|
||||
"Print target name, but do not change anything");
|
||||
|
||||
sub.add_option("--flags", opts.move.flags, "Target flags")
|
||||
->type_name("<flags>");
|
||||
|
||||
sub.add_option("source", opts.move.src, "Message file to move")
|
||||
->type_name("<message-path>")
|
||||
->transform(ExpandPath, "expand path")
|
||||
->transform(CanonicalizePath, "canonicalize path")
|
||||
->required();
|
||||
sub.add_option("destination", opts.move.dest,
|
||||
"Destination maildir")
|
||||
->type_name("<maildir>");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sub_remove(CLI::App& sub, Options& opts)
|
||||
{
|
||||
@ -602,7 +633,7 @@ AssocPairs<SubCommand, CommandInfo, Options::SubCommandNum> SubCommandInfos= {{
|
||||
},
|
||||
{ SubCommand::Info,
|
||||
{Category::NeedsReadOnlyStore,
|
||||
"info", "Show information about the message store database", sub_info }
|
||||
"info", "Show information", sub_info }
|
||||
},
|
||||
{ SubCommand::Init,
|
||||
{Category::NeedsWritableStore,
|
||||
@ -612,6 +643,10 @@ AssocPairs<SubCommand, CommandInfo, Options::SubCommandNum> SubCommandInfos= {{
|
||||
{Category::None,
|
||||
"mkdir", "Create a new Maildir", sub_mkdir }
|
||||
},
|
||||
{ SubCommand::Move,
|
||||
{Category::NeedsWritableStore,
|
||||
"move", "Move a message or change flags", sub_move }
|
||||
},
|
||||
{ SubCommand::Remove,
|
||||
{Category::NeedsWritableStore,
|
||||
"remove", "Remove message from file-system and database", sub_remove }
|
||||
@ -718,7 +753,8 @@ add_global_options(CLI::App& cli, Options& opts)
|
||||
|
||||
cli.add_flag("-q,--quiet", opts.quiet, "Hide non-essential output");
|
||||
cli.add_flag("-v,--verbose", opts.verbose, "Show verbose output");
|
||||
cli.add_flag("--log-stderr", opts.log_stderr, "Log to stderr");
|
||||
cli.add_flag("--log-stderr", opts.log_stderr, "Log to stderr")
|
||||
->group(""/*always hide*/);
|
||||
cli.add_flag("--nocolor", opts.nocolor, "Don't show ANSI colors")
|
||||
->default_val(Options::default_no_color())
|
||||
->default_str(Options::default_no_color() ? "<true>" : "<false>");
|
||||
@ -780,7 +816,7 @@ There is NO WARRANTY, to the extent permitted by law.
|
||||
->transform(ExpandPath, "expand path");
|
||||
}
|
||||
|
||||
/* add scripts (if supported) as semi-subscommands as well */
|
||||
/* add scripts (if supported) as semi-subcommands as well */
|
||||
const auto scripts = add_scripts(app, opts);
|
||||
|
||||
try {
|
||||
@ -842,6 +878,11 @@ Options::category(Options::SubCommand sub)
|
||||
static constexpr bool
|
||||
validate_subcommand_ids()
|
||||
{
|
||||
size_t val{};
|
||||
for (auto& cmd: Options::SubCommands)
|
||||
if (static_cast<size_t>(cmd) != val++)
|
||||
return false;
|
||||
|
||||
for (auto u = 0U; u != SubCommandInfos.size(); ++u)
|
||||
if (static_cast<size_t>(SubCommandInfos.at(u).first) != u)
|
||||
return false;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
@ -36,10 +36,10 @@
|
||||
/* command-line options for Mu */
|
||||
namespace Mu {
|
||||
struct Options {
|
||||
using OptSize = Option<std::size_t>;
|
||||
using SizeVec = std::vector<std::size_t>;
|
||||
using OptTStamp = Option<std::time_t>;
|
||||
using OptFieldId = Option<Field::Id>;
|
||||
using OptSize = Option<std::size_t>;
|
||||
using SizeVec = std::vector<std::size_t>;
|
||||
using OptTStamp = Option<std::time_t>;
|
||||
using OptFieldId = Option<Field::Id>;
|
||||
using StringVec = std::vector<std::string>;
|
||||
|
||||
/*
|
||||
@ -62,10 +62,11 @@ struct Options {
|
||||
|
||||
enum struct SubCommand {
|
||||
Add, Cfind, Extract, Fields, Find, Help, Index,Info, Init, Mkdir,
|
||||
Remove, Script, Server, Verify, View/*must be last*/
|
||||
Move, Remove, Script, Server, Verify, View,
|
||||
// <private>
|
||||
__count__
|
||||
};
|
||||
static constexpr std::size_t SubCommandNum =
|
||||
1 + static_cast<std::size_t>(SubCommand::View);
|
||||
static constexpr auto SubCommandNum = static_cast<size_t>(SubCommand::__count__);
|
||||
static constexpr std::array<SubCommand, SubCommandNum> SubCommands = {{
|
||||
SubCommand::Add,
|
||||
SubCommand::Cfind,
|
||||
@ -77,6 +78,7 @@ struct Options {
|
||||
SubCommand::Info,
|
||||
SubCommand::Init,
|
||||
SubCommand::Mkdir,
|
||||
SubCommand::Move,
|
||||
SubCommand::Remove,
|
||||
SubCommand::Script,
|
||||
SubCommand::Server,
|
||||
@ -84,7 +86,6 @@ struct Options {
|
||||
SubCommand::View
|
||||
}};
|
||||
|
||||
|
||||
Option<SubCommand> sub_command; /**< The chosen sub-command, if any. */
|
||||
|
||||
/*
|
||||
@ -117,16 +118,16 @@ struct Options {
|
||||
* Extract
|
||||
*/
|
||||
struct Extract: public Crypto {
|
||||
std::string message; /**< path to message file */
|
||||
std::string message; /**< path to message file */
|
||||
bool save_all; /**< extract all parts */
|
||||
bool save_attachments; /**< extract all attachment parts */
|
||||
SizeVec parts; /**< parts to save / open */
|
||||
SizeVec parts; /**< parts to save / open */
|
||||
std::string targetdir{}; /**< where to save attachments */
|
||||
bool overwrite; /**< overwrite same-named files */
|
||||
bool play; /**< try to 'play' attachment */
|
||||
std::string filename_rx; /**< Filename rx to save */
|
||||
bool uncooked{}; /**< Whether to avoid massaging
|
||||
* output filename */
|
||||
std::string filename_rx; /**< Filename rx to save */
|
||||
bool uncooked{}; /**< Whether to avoid massaging
|
||||
* the output filename */
|
||||
} extract;
|
||||
|
||||
/*
|
||||
@ -138,7 +139,7 @@ struct Options {
|
||||
*/
|
||||
struct Find {
|
||||
std::string fields; /**< fields to show in output */
|
||||
Field::Id sortfield; /**< field to sort by */
|
||||
Field::Id sortfield; /**< field to sort by */
|
||||
OptSize maxnum; /**< max # of entries to print */
|
||||
bool reverse; /**< sort in revers order (z->a) */
|
||||
bool threads; /**< show message threads */
|
||||
@ -146,7 +147,7 @@ struct Options {
|
||||
std::string linksdir; /**< directory for links */
|
||||
OptSize summary_len; /**< max # of lines for summary */
|
||||
std::string bookmark; /**< use bookmark */
|
||||
bool analyze; /**< analyze query */
|
||||
bool analyze; /**< analyze query */
|
||||
|
||||
enum struct Format { Plain, Links, Xml, Json, Sexp, Exec };
|
||||
Format format; /**< Output format */
|
||||
@ -158,7 +159,7 @@ struct Options {
|
||||
bool auto_retrieve; /**< assume we're online */
|
||||
bool decrypt; /**< try to decrypt the body */
|
||||
|
||||
StringVec query; /**< search query */
|
||||
StringVec query; /**< search query */
|
||||
} find;
|
||||
|
||||
struct Help {
|
||||
@ -189,10 +190,10 @@ struct Options {
|
||||
StringVec my_addresses; /**< personal e-mail addresses */
|
||||
StringVec ignored_addresses; /**< addresses to be ignored for
|
||||
* the contacts-cache */
|
||||
OptSize max_msg_size; /**< max size for message files */
|
||||
OptSize max_msg_size; /**< max size for message files */
|
||||
OptSize batch_size; /**< db transaction batch size */
|
||||
bool reinit; /**< re-initialize */
|
||||
bool support_ngrams; /**< support CJK etc. ngrams */
|
||||
bool support_ngrams; /**< support CJK etc. ngrams */
|
||||
|
||||
} init;
|
||||
|
||||
@ -204,6 +205,19 @@ struct Options {
|
||||
mode_t mode; /**< Mode for the maildir */
|
||||
} mkdir;
|
||||
|
||||
/*
|
||||
* Move
|
||||
*/
|
||||
struct Move {
|
||||
std::string src; /**< Source file */
|
||||
std::string dest; /**< Destination dir */
|
||||
std::string flags; /**< Flags for destination */
|
||||
bool change_name; /**< Change basename for destination */
|
||||
bool update_dups; /**< Update duplicate messages too */
|
||||
bool dry_run; /**< Just print the result path,
|
||||
but do not change anything */
|
||||
} move;
|
||||
|
||||
/*
|
||||
* Remove
|
||||
*/
|
||||
@ -215,7 +229,7 @@ struct Options {
|
||||
* Scripts (i.e., finding scriot)
|
||||
*/
|
||||
struct Script {
|
||||
std::string name; /**< name of script */
|
||||
std::string name; /**< name of script */
|
||||
StringVec params; /**< script params */
|
||||
} script;
|
||||
|
||||
@ -225,7 +239,7 @@ struct Options {
|
||||
struct Server {
|
||||
bool commands; /**< dump docs for commands */
|
||||
std::string eval; /**< command to evaluate */
|
||||
bool allow_temp_file; /**< temp-file optimization allowed? */
|
||||
bool allow_temp_file; /**< temp-file optimization allowed? */
|
||||
} server;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user