342 lines
11 KiB
C++
342 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) version 3.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef INCL_SYNC_EVOLUTION_CMDLINE
|
|
# define INCL_SYNC_EVOLUTION_CMDLINE
|
|
|
|
#include <syncevo/SyncConfig.h>
|
|
#include <syncevo/FilterConfigNode.h>
|
|
#include <syncevo/util.h>
|
|
|
|
#include <set>
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/scoped_array.hpp>
|
|
|
|
#include <syncevo/declarations.h>
|
|
SE_BEGIN_CXX
|
|
|
|
class SyncSource;
|
|
class SyncSourceRaw;
|
|
class SyncContext;
|
|
class CmdlineTest;
|
|
|
|
/**
|
|
* encodes a locally unique ID (LUID) in such a
|
|
* way that it is treated as a plain word by shells
|
|
*/
|
|
class CmdlineLUID
|
|
{
|
|
std::string m_encodedLUID;
|
|
|
|
public:
|
|
/** fill with encoded LUID */
|
|
void setEncoded(const std::string &encodedLUID) { m_encodedLUID = encodedLUID; }
|
|
|
|
/** return encoded LUID as string */
|
|
std::string getEncoded() const { return m_encodedLUID; }
|
|
|
|
/** return original LUID */
|
|
std::string toLUID() const { return toLUID(m_encodedLUID); }
|
|
static std::string toLUID(const std::string &encoded) { return StringEscape::unescape(encoded, '%'); }
|
|
|
|
/** fill with unencoded LUID */
|
|
void setLUID(const std::string &luid) { m_encodedLUID = fromLUID(luid); }
|
|
|
|
/** convert from unencoded LUID */
|
|
static std::string fromLUID(const std::string &luid) { return StringEscape::escape(luid, '%', StringEscape::STRICT); }
|
|
};
|
|
|
|
class Cmdline {
|
|
public:
|
|
Cmdline(int argc, const char * const *argv);
|
|
Cmdline(const std::vector<std::string> &args);
|
|
Cmdline(const char *arg, ...);
|
|
virtual ~Cmdline() {}
|
|
|
|
/**
|
|
* parse the command line options
|
|
*
|
|
* @retval true if command line was okay
|
|
*/
|
|
bool parse();
|
|
|
|
/**
|
|
* parse the command line options
|
|
* relative paths in the arguments are converted to absolute paths
|
|
* if it returns false, then the content of args is undefined.
|
|
*
|
|
* @retval true if command line was okay
|
|
*/
|
|
bool parse(std::vector<std::string> &args);
|
|
|
|
/**
|
|
* @return false if run() still needs to be invoked, true when parse() already did
|
|
* the job (like --sync-property ?)
|
|
*/
|
|
bool dontRun() const;
|
|
|
|
bool run();
|
|
|
|
/**
|
|
* sync report as owned by this instance, not filled in unless
|
|
* run() executed a sync
|
|
*/
|
|
const SyncReport &getReport() const { return m_report; }
|
|
|
|
/** the run() call modified configurations (added, updated, removed) */
|
|
bool configWasModified() const { return m_configModified; }
|
|
|
|
Bool useDaemon() { return m_useDaemon; }
|
|
|
|
/** whether '--monitor' is set */
|
|
bool monitor() { return m_monitor; }
|
|
|
|
/** whether 'status' is set */
|
|
bool status() { return m_status; }
|
|
|
|
/* server name */
|
|
std::string getConfigName() { return m_server; }
|
|
|
|
/* check whether command line runs sync. It should be called after parsing. */
|
|
bool isSync();
|
|
/** same as isSync() for --restore */
|
|
bool isRestore() const;
|
|
|
|
protected:
|
|
// vector to store strings for arguments
|
|
std::vector<std::string> m_args;
|
|
|
|
int m_argc;
|
|
const char * const * m_argv;
|
|
|
|
//array to store pointers of arguments
|
|
boost::scoped_array<const char *> m_argvArray;
|
|
|
|
/** result of sync, if one was executed */
|
|
SyncReport m_report;
|
|
|
|
Bool m_quiet;
|
|
Bool m_dryrun;
|
|
Bool m_status;
|
|
Bool m_version;
|
|
Bool m_usage;
|
|
Bool m_configure;
|
|
Bool m_remove;
|
|
Bool m_run;
|
|
Bool m_migrate;
|
|
Bool m_printDatabases;
|
|
Bool m_createDatabase;
|
|
Bool m_removeDatabase;
|
|
Bool m_printServers;
|
|
Bool m_printTemplates;
|
|
Bool m_printConfig;
|
|
Bool m_printSessions;
|
|
Bool m_dontrun;
|
|
Bool m_monitor;
|
|
Bool m_useDaemon;
|
|
FullProps m_props;
|
|
const ConfigPropertyRegistry &m_validSyncProps;
|
|
const ConfigPropertyRegistry &m_validSourceProps;
|
|
|
|
std::string m_restore;
|
|
Bool m_before, m_after;
|
|
|
|
Bool m_accessItems;
|
|
std::string m_itemPath;
|
|
std::string m_delimiter;
|
|
std::list<std::string> m_luids;
|
|
Bool m_printItems, m_update, m_import, m_export, m_deleteItems;
|
|
|
|
std::string m_server;
|
|
std::string m_template;
|
|
std::set<std::string> m_sources;
|
|
|
|
/** running the command line modified configuration settings (add, update, remove) */
|
|
Bool m_configModified;
|
|
|
|
/** compose description of cmd line option with optional parameter */
|
|
static std::string cmdOpt(const char *opt, const char *param = NULL);
|
|
|
|
/**
|
|
* rename file or directory by appending .old or (if that already
|
|
* exists) .old.x for x >= 1; updates config to point to the renamed directory
|
|
*/
|
|
void makeObsolete(boost::shared_ptr<SyncConfig> &from);
|
|
|
|
/**
|
|
* Copy from one config into another, with filters
|
|
* applied for the target. All sources are copied
|
|
* if selectedSources is empty, otherwise only
|
|
* those.
|
|
*/
|
|
void copyConfig(const boost::shared_ptr<SyncConfig> &from,
|
|
const boost::shared_ptr<SyncConfig> &to,
|
|
const std::set<std::string> &selectedSources);
|
|
|
|
/**
|
|
* flush, move .synthesis dir, set ConsumerReady, ...
|
|
*/
|
|
void finishCopy(const boost::shared_ptr<SyncConfig> &from,
|
|
const boost::shared_ptr<SyncContext> &to);
|
|
|
|
/**
|
|
* migrate peer config; target context must be ready
|
|
*/
|
|
void migratePeer(const std::string &fromPeer, const std::string &toPeer);
|
|
|
|
/**
|
|
* parse sync or source property
|
|
*
|
|
* @param propertyType sync, source, or unknown (in which case the property name must be given and must be unique)
|
|
* @param opt command line option as it appeard in argv (e.g. --sync|--sync-property|-z)
|
|
* @param param the parameter following the opt, may be NULL if none given (error!)
|
|
* @param propname if given, then this is the property name and param contains the param value (--sync <param>)
|
|
*/
|
|
|
|
bool parseProp(PropertyType propertyType,
|
|
const char *opt,
|
|
const char *param,
|
|
const char *propname = NULL);
|
|
|
|
/**
|
|
* parse keyword which sets a certain property,
|
|
* like --sync=two-way, --sync two-way, ... for the "sync" property
|
|
*
|
|
* If a default value is give, then the format is like:
|
|
* --keyring[=<def>], --keyring=<value>, ...
|
|
* but not
|
|
* --keyring <value>
|
|
*/
|
|
bool parseAssignment(int &opt, std::vector<std::string> &parsed,
|
|
PropertyType propertyType,
|
|
const char *propname,
|
|
const char *def);
|
|
|
|
bool listPropValues(const ConfigPropertyRegistry &validProps,
|
|
const std::string &propName,
|
|
const std::string &opt);
|
|
|
|
bool listProperties(const ConfigPropertyRegistry &validProps,
|
|
const std::string &opt);
|
|
|
|
/**
|
|
* check that m_props don't contain
|
|
* properties which only apply to peers, throw error
|
|
* if found
|
|
*/
|
|
void checkForPeerProps();
|
|
|
|
/**
|
|
* list all known data sources of a certain type
|
|
*/
|
|
void listDatabases(SyncSource *source, const std::string &header);
|
|
void createDatabase(SyncSource *source, const std::string &header);
|
|
void removeDatabase(SyncSource *source, const std::string &header);
|
|
|
|
void dumpConfigs(const std::string &preamble,
|
|
const SyncConfig::ConfigList &servers);
|
|
|
|
void dumpConfigTemplates(const std::string &preamble,
|
|
const SyncConfig::TemplateList &templates,
|
|
bool printRank = false,
|
|
Logger::Level level = Logger::SHOW);
|
|
|
|
enum DumpPropertiesFlags {
|
|
DUMP_PROPS_NORMAL = 0,
|
|
HIDE_LEGEND = 1<<0, /**<
|
|
* do not show the explanation which properties are shared,
|
|
* used while dumping any source which is not the last one
|
|
*/
|
|
HIDE_PER_PEER = 1<<1 /**<
|
|
* config is for a context, not a peer, so do not show those
|
|
* properties which are only per-peer
|
|
*/
|
|
};
|
|
void dumpProperties(const ConfigNode &configuredProps,
|
|
const ConfigPropertyRegistry &allProps,
|
|
int flags);
|
|
|
|
void copyProperties(const ConfigNode &fromProps,
|
|
ConfigNode &toProps,
|
|
bool hidden,
|
|
const ConfigPropertyRegistry &allProps);
|
|
|
|
void dumpComment(std::ostream &stream,
|
|
const std::string &prefix,
|
|
const std::string &comment);
|
|
|
|
/** ensure that m_server was set, false if error message was necessary */
|
|
bool needConfigName();
|
|
|
|
/** print usage information */
|
|
void usage(bool full,
|
|
const std::string &error = std::string(""),
|
|
const std::string ¶m = std::string(""));
|
|
|
|
/**
|
|
* This is a factory method used to delay sync client creation to its
|
|
* subclass. The motivation is to let user implement their own
|
|
* clients to avoid dependency.
|
|
* @return the created sync client
|
|
*/
|
|
virtual SyncContext* createSyncClient();
|
|
|
|
friend class CmdlineTest;
|
|
|
|
private:
|
|
/**
|
|
* Utility function to check m_argv[opt] against a specific boolean
|
|
* parameter of the form "<longName|shortName>[=yes/1/t/true/no/0/f/false].
|
|
*
|
|
* @param opt current index in m_argv
|
|
* @param longName long form of the parameter, including --, may be NULL
|
|
* @param shortName short form, including -, may be NULL
|
|
* @param def default value if m_argv[opt] contains no explicit value
|
|
* @retval value if and only if m_argv[opt] matches, then this is set to to true or false
|
|
* @retval ok true if parsing succeeded, false if not and error message was printed
|
|
*/
|
|
bool parseBool(int opt, const char *longName, const char *shortName,
|
|
bool def, Bool &value,
|
|
bool &ok);
|
|
|
|
/**
|
|
* Fill list with all local IDs of the given source, as used by the source.
|
|
*/
|
|
void readLUIDs(SyncSource *source, std::list<std::string> &luids);
|
|
|
|
/**
|
|
* Invoke a callback for each local ID.
|
|
*/
|
|
void processLUIDs(SyncSource *source, const boost::function<void (const std::string &)> &callback);
|
|
|
|
/**
|
|
* Add or update one item.
|
|
* @param source SyncSource in write mode (startWriteData must have been called)
|
|
* @param luid local ID, empty if item is to be added
|
|
* @param data the item data to insert
|
|
* @return encoded luid of inserted item
|
|
*/
|
|
CmdlineLUID insertItem(SyncSourceRaw *source, const std::string &luid, const std::string &data);
|
|
};
|
|
|
|
|
|
SE_END_CXX
|
|
#endif // INCL_SYNC_EVOLUTION_CMDLINE
|