syncevolution/src/syncevo/Cmdline.cpp

3982 lines
167 KiB
C++
Raw Normal View History

/*
* Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
* Copyright (C) 2009 Intel Corporation
*
* 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
*/
#include <syncevo/Cmdline.h>
#include <syncevo/FilterConfigNode.h>
#include <syncevo/VolatileConfigNode.h>
#include <syncevo/IniConfigNode.h>
#include <syncevo/SyncSource.h>
#include <syncevo/SyncContext.h>
#include <syncevo/util.h>
#include "test.h"
#include <unistd.h>
#include <errno.h>
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <memory>
#include <set>
#include <list>
#include <algorithm>
using namespace std;
#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string/join.hpp>
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/range.hpp>
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
#include <fstream>
#include <syncevo/declarations.h>
SE_BEGIN_CXX
// synopsis and options char strings
#include "CmdlineHelp.c"
Cmdline::Cmdline(int argc, const char * const * argv, ostream &out, ostream &err) :
m_argc(argc),
m_argv(argv),
m_out(out),
m_err(err),
m_validSyncProps(SyncConfig::getRegistry()),
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
m_validSourceProps(SyncSourceConfig::getRegistry())
{}
Cmdline::Cmdline(const vector<string> &args, ostream &out, ostream &err) :
m_args(args),
m_out(out),
m_err(err),
m_validSyncProps(SyncConfig::getRegistry()),
m_validSourceProps(SyncSourceConfig::getRegistry())
{
m_argc = args.size();
m_argvArray.reset(new const char *[args.size()]);
for(int i = 0; i < m_argc; i++) {
m_argvArray[i] = m_args[i].c_str();
}
m_argv = m_argvArray.get();
}
Cmdline::Cmdline(ostream &out, ostream &err, const char *arg, ...) :
m_out(out),
m_err(err),
m_validSyncProps(SyncConfig::getRegistry()),
m_validSourceProps(SyncSourceConfig::getRegistry())
{
va_list argList;
va_start(argList, arg);
for (const char *curr = arg;
curr;
curr = va_arg(argList, const char *)) {
m_args.push_back(curr);
}
va_end(argList);
m_argc = m_args.size();
m_argvArray.reset(new const char *[m_args.size()]);
for (int i = 0; i < m_argc; i++) {
m_argvArray[i] = m_args[i].c_str();
}
m_argv = m_argvArray.get();
}
bool Cmdline::parse()
{
vector<string> parsed;
return parse(parsed);
}
bool Cmdline::parse(vector<string> &parsed)
{
parsed.clear();
if (m_argc) {
parsed.push_back(m_argv[0]);
}
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
m_delimiter = "\n\n";
// All command line options which ask for a specific operation,
// like --restore, --print-config, ... Used to detect conflicting
// operations.
vector<string> operations;
int opt = 1;
command line + daemon: usability improvements (MB #5043) This patch changes what is shown to the user and how the user interacts with the command line. Details below. "--use-daemon [yes/no]" implies that yes/no is optional (square brackets!), with "yes" being the option that could be expected for a plain "--use-daemon" parameter. But the implementation always expects a "yes" or "no" parameter. The original format suggested was "--use-daemon[=yes/no]" This patch switches to that format, changes --use-daemon into --daemon (to be consistent with --keyring) and enables the same format for --keyring. Although not documented, 0/f/false and 1/t/true are also accepted. Because the value becomes part of the parameter, m_argc checks had to be adapted. The documentation for "--use-daemon" was inserted in the middle of the "--keyring documentation". "Parameter not set" has to be available to the Cmdline caller in the command line too, in addition to true/false. This was done originally with a string which is empty, "yes" or "no". Using a tri-state Cmdline::Bool class makes this a bit more explicit and removes the ambiguity around what useDaemon() returns (values weren't documented). When running without --daemon and no daemon available, the first lines of output were: ERROR: org.<cryptic error> [INFO] itodo20: inactive .... => The command line should fall back *silently* to running in-process. => Error messages should be formatted and logged as such, using SE_LOG_ERROR(). Old code might not have done that and we need to preserve that for compatibility with frontends, but new code should use [ERROR] as output. => D-Bus error messages (as in the case above) must have some user (and developer!) comprehensible explanation what went wrong. The D-Bus error class itself is no enough. Although I haven't tested it, I suspect that the code also would have re-run the operation in-process after the D-Bus server already executed it and failed. I rewrote this so that a check for "daemon available" without error messages is done first before committing to using the daemon. Once that decision is made, the command line will not fall back to in-process execution. Rewrote several error messages. Telling a user of a distro's binary to "re-configure" is misleading (he didn't configure himself). "can't" => "cannot", punctuation changes. Not sure whether is always an improvement, comments welcome. Comment on coding style: I've used "if ()" instead of "if()" because that is the GNU recommendation.
2010-03-26 18:47:41 +01:00
bool ok;
while (opt < m_argc) {
parsed.push_back(m_argv[opt]);
if (m_argv[opt][0] != '-') {
break;
}
if (boost::iequals(m_argv[opt], "--sync") ||
boost::iequals(m_argv[opt], "-s")) {
opt++;
string param;
string cmdopt(m_argv[opt - 1]);
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
if (!parseProp(SOURCE_PROPERTY_TYPE,
m_argv[opt - 1], opt == m_argc ? NULL : m_argv[opt],
"sync")) {
return false;
}
parsed.push_back(m_argv[opt]);
// disable requirement to add --run explicitly in order to
// be compatible with traditional command lines
m_run = true;
} else if(boost::iequals(m_argv[opt], "--sync-property") ||
boost::iequals(m_argv[opt], "-y")) {
opt++;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
if (!parseProp(SYNC_PROPERTY_TYPE,
m_argv[opt - 1], opt == m_argc ? NULL : m_argv[opt])) {
return false;
}
parsed.push_back(m_argv[opt]);
} else if(boost::iequals(m_argv[opt], "--source-property") ||
boost::iequals(m_argv[opt], "-z")) {
opt++;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
if (!parseProp(SOURCE_PROPERTY_TYPE,
m_argv[opt - 1], opt == m_argc ? NULL : m_argv[opt])) {
return false;
}
parsed.push_back(m_argv[opt]);
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
}else if(boost::iequals(m_argv[opt], "--template") ||
boost::iequals(m_argv[opt], "-l")) {
opt++;
if (opt >= m_argc) {
usage(true, string("missing parameter for ") + cmdOpt(m_argv[opt - 1]));
return false;
}
parsed.push_back(m_argv[opt]);
m_template = m_argv[opt];
m_configure = true;
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
string temp = boost::trim_copy (m_template);
if (temp.find ("?") == 0){
m_printTemplates = true;
m_dontrun = true;
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
m_template = temp.substr (1);
}
} else if(boost::iequals(m_argv[opt], "--print-servers") ||
boost::iequals(m_argv[opt], "--print-peers") ||
boost::iequals(m_argv[opt], "--print-configs")) {
operations.push_back(m_argv[opt]);
m_printServers = true;
} else if(boost::iequals(m_argv[opt], "--print-config") ||
boost::iequals(m_argv[opt], "-p")) {
operations.push_back(m_argv[opt]);
m_printConfig = true;
} else if(boost::iequals(m_argv[opt], "--print-sessions")) {
operations.push_back(m_argv[opt]);
m_printSessions = true;
} else if(boost::iequals(m_argv[opt], "--configure") ||
boost::iequals(m_argv[opt], "-c")) {
operations.push_back(m_argv[opt]);
m_configure = true;
} else if(boost::iequals(m_argv[opt], "--remove")) {
operations.push_back(m_argv[opt]);
m_remove = true;
} else if(boost::iequals(m_argv[opt], "--run") ||
boost::iequals(m_argv[opt], "-r")) {
operations.push_back(m_argv[opt]);
m_run = true;
} else if(boost::iequals(m_argv[opt], "--restore")) {
operations.push_back(m_argv[opt]);
opt++;
if (opt >= m_argc) {
usage(true, string("missing parameter for ") + cmdOpt(m_argv[opt - 1]));
return false;
}
m_restore = m_argv[opt];
if (m_restore.empty()) {
usage(true, string("missing parameter for ") + cmdOpt(m_argv[opt - 1]));
return false;
}
//if can't convert it successfully, it's an invalid path
if (!relToAbs(m_restore)) {
usage(true, string("parameter '") + m_restore + "' for " + cmdOpt(m_argv[opt - 1]) + " must be log directory");
return false;
}
parsed.push_back(m_restore);
} else if(boost::iequals(m_argv[opt], "--before")) {
m_before = true;
} else if(boost::iequals(m_argv[opt], "--after")) {
m_after = true;
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
} else if (boost::iequals(m_argv[opt], "--print-items")) {
operations.push_back(m_argv[opt]);
m_printItems = m_accessItems = true;
} else if ((boost::iequals(m_argv[opt], "--export") && (m_export = true)) ||
(boost::iequals(m_argv[opt], "--import") && (m_import = true)) ||
(boost::iequals(m_argv[opt], "--update") && (m_update = true))) {
operations.push_back(m_argv[opt]);
m_accessItems = true;
opt++;
if (opt >= m_argc || !m_argv[opt][0]) {
usage(true, string("missing parameter for ") + cmdOpt(m_argv[opt - 1]));
return false;
}
m_itemPath = m_argv[opt];
if (m_itemPath != "-") {
string dir, file;
splitPath(m_itemPath, dir, file);
if (dir.empty()) {
dir = ".";
}
if (!relToAbs(dir)) {
SyncContext::throwError(dir, errno);
}
m_itemPath = dir + "/" + file;
}
parsed.push_back(m_itemPath);
} else if (boost::iequals(m_argv[opt], "--delimiter")) {
opt++;
if (opt >= m_argc) {
usage(true, string("missing parameter for ") + cmdOpt(m_argv[opt - 1]));
return false;
}
m_delimiter = m_argv[opt];
parsed.push_back(m_delimiter);
} else if (boost::iequals(m_argv[opt], "--delete-items")) {
operations.push_back(m_argv[opt]);
m_deleteItems = m_accessItems = true;
} else if(boost::iequals(m_argv[opt], "--dry-run")) {
m_dryrun = true;
} else if(boost::iequals(m_argv[opt], "--migrate")) {
operations.push_back(m_argv[opt]);
m_migrate = true;
} else if(boost::iequals(m_argv[opt], "--status") ||
boost::iequals(m_argv[opt], "-t")) {
operations.push_back(m_argv[opt]);
m_status = true;
} else if(boost::iequals(m_argv[opt], "--quiet") ||
boost::iequals(m_argv[opt], "-q")) {
m_quiet = true;
} else if(boost::iequals(m_argv[opt], "--help") ||
boost::iequals(m_argv[opt], "-h")) {
m_usage = true;
} else if(boost::iequals(m_argv[opt], "--version")) {
operations.push_back(m_argv[opt]);
m_version = true;
command line + daemon: usability improvements (MB #5043) This patch changes what is shown to the user and how the user interacts with the command line. Details below. "--use-daemon [yes/no]" implies that yes/no is optional (square brackets!), with "yes" being the option that could be expected for a plain "--use-daemon" parameter. But the implementation always expects a "yes" or "no" parameter. The original format suggested was "--use-daemon[=yes/no]" This patch switches to that format, changes --use-daemon into --daemon (to be consistent with --keyring) and enables the same format for --keyring. Although not documented, 0/f/false and 1/t/true are also accepted. Because the value becomes part of the parameter, m_argc checks had to be adapted. The documentation for "--use-daemon" was inserted in the middle of the "--keyring documentation". "Parameter not set" has to be available to the Cmdline caller in the command line too, in addition to true/false. This was done originally with a string which is empty, "yes" or "no". Using a tri-state Cmdline::Bool class makes this a bit more explicit and removes the ambiguity around what useDaemon() returns (values weren't documented). When running without --daemon and no daemon available, the first lines of output were: ERROR: org.<cryptic error> [INFO] itodo20: inactive .... => The command line should fall back *silently* to running in-process. => Error messages should be formatted and logged as such, using SE_LOG_ERROR(). Old code might not have done that and we need to preserve that for compatibility with frontends, but new code should use [ERROR] as output. => D-Bus error messages (as in the case above) must have some user (and developer!) comprehensible explanation what went wrong. The D-Bus error class itself is no enough. Although I haven't tested it, I suspect that the code also would have re-run the operation in-process after the D-Bus server already executed it and failed. I rewrote this so that a check for "daemon available" without error messages is done first before committing to using the daemon. Once that decision is made, the command line will not fall back to in-process execution. Rewrote several error messages. Telling a user of a distro's binary to "re-configure" is misleading (he didn't configure himself). "can't" => "cannot", punctuation changes. Not sure whether is always an improvement, comments welcome. Comment on coding style: I've used "if ()" instead of "if()" because that is the GNU recommendation.
2010-03-26 18:47:41 +01:00
} else if (parseBool(opt, "--keyring", "-k", true, m_keyring, ok)) {
if (!ok) {
return false;
}
command line + daemon: usability improvements (MB #5043) This patch changes what is shown to the user and how the user interacts with the command line. Details below. "--use-daemon [yes/no]" implies that yes/no is optional (square brackets!), with "yes" being the option that could be expected for a plain "--use-daemon" parameter. But the implementation always expects a "yes" or "no" parameter. The original format suggested was "--use-daemon[=yes/no]" This patch switches to that format, changes --use-daemon into --daemon (to be consistent with --keyring) and enables the same format for --keyring. Although not documented, 0/f/false and 1/t/true are also accepted. Because the value becomes part of the parameter, m_argc checks had to be adapted. The documentation for "--use-daemon" was inserted in the middle of the "--keyring documentation". "Parameter not set" has to be available to the Cmdline caller in the command line too, in addition to true/false. This was done originally with a string which is empty, "yes" or "no". Using a tri-state Cmdline::Bool class makes this a bit more explicit and removes the ambiguity around what useDaemon() returns (values weren't documented). When running without --daemon and no daemon available, the first lines of output were: ERROR: org.<cryptic error> [INFO] itodo20: inactive .... => The command line should fall back *silently* to running in-process. => Error messages should be formatted and logged as such, using SE_LOG_ERROR(). Old code might not have done that and we need to preserve that for compatibility with frontends, but new code should use [ERROR] as output. => D-Bus error messages (as in the case above) must have some user (and developer!) comprehensible explanation what went wrong. The D-Bus error class itself is no enough. Although I haven't tested it, I suspect that the code also would have re-run the operation in-process after the D-Bus server already executed it and failed. I rewrote this so that a check for "daemon available" without error messages is done first before committing to using the daemon. Once that decision is made, the command line will not fall back to in-process execution. Rewrote several error messages. Telling a user of a distro's binary to "re-configure" is misleading (he didn't configure himself). "can't" => "cannot", punctuation changes. Not sure whether is always an improvement, comments welcome. Comment on coding style: I've used "if ()" instead of "if()" because that is the GNU recommendation.
2010-03-26 18:47:41 +01:00
} else if (parseBool(opt, "--daemon", NULL, true, m_useDaemon, ok)) {
if (!ok) {
return false;
}
} else if(boost::iequals(m_argv[opt], "--monitor")||
boost::iequals(m_argv[opt], "-m")) {
operations.push_back(m_argv[opt]);
m_monitor = true;
} else {
usage(false, string(m_argv[opt]) + ": unknown parameter");
return false;
}
opt++;
}
if (opt < m_argc) {
m_server = m_argv[opt++];
while (opt < m_argc) {
parsed.push_back(m_argv[opt]);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
if (m_sources.empty() ||
!m_accessItems) {
m_sources.insert(m_argv[opt++]);
} else {
// first additional parameter was source, rest are luids
m_luids.push_back(CmdlineLUID::toLUID(m_argv[opt++]));
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
}
}
}
// check whether we have conflicting operations requested by user
if (operations.size() > 1) {
usage(false, boost::join(operations, " ") + ": mutually exclusive operations");
return false;
}
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
// common sanity checking for item listing/import/export/update
if (m_accessItems) {
if (m_server.empty()) {
usage(false, operations[0] + ": needs configuration name");
return false;
}
if (m_sources.size() == 0) {
usage(false, operations[0] + ": needs source name");
return false;
}
if ((m_import || m_update) && m_dryrun) {
usage(false, operations[0] + ": --dry-run not supported");
return false;
}
}
return true;
}
command line + daemon: usability improvements (MB #5043) This patch changes what is shown to the user and how the user interacts with the command line. Details below. "--use-daemon [yes/no]" implies that yes/no is optional (square brackets!), with "yes" being the option that could be expected for a plain "--use-daemon" parameter. But the implementation always expects a "yes" or "no" parameter. The original format suggested was "--use-daemon[=yes/no]" This patch switches to that format, changes --use-daemon into --daemon (to be consistent with --keyring) and enables the same format for --keyring. Although not documented, 0/f/false and 1/t/true are also accepted. Because the value becomes part of the parameter, m_argc checks had to be adapted. The documentation for "--use-daemon" was inserted in the middle of the "--keyring documentation". "Parameter not set" has to be available to the Cmdline caller in the command line too, in addition to true/false. This was done originally with a string which is empty, "yes" or "no". Using a tri-state Cmdline::Bool class makes this a bit more explicit and removes the ambiguity around what useDaemon() returns (values weren't documented). When running without --daemon and no daemon available, the first lines of output were: ERROR: org.<cryptic error> [INFO] itodo20: inactive .... => The command line should fall back *silently* to running in-process. => Error messages should be formatted and logged as such, using SE_LOG_ERROR(). Old code might not have done that and we need to preserve that for compatibility with frontends, but new code should use [ERROR] as output. => D-Bus error messages (as in the case above) must have some user (and developer!) comprehensible explanation what went wrong. The D-Bus error class itself is no enough. Although I haven't tested it, I suspect that the code also would have re-run the operation in-process after the D-Bus server already executed it and failed. I rewrote this so that a check for "daemon available" without error messages is done first before committing to using the daemon. Once that decision is made, the command line will not fall back to in-process execution. Rewrote several error messages. Telling a user of a distro's binary to "re-configure" is misleading (he didn't configure himself). "can't" => "cannot", punctuation changes. Not sure whether is always an improvement, comments welcome. Comment on coding style: I've used "if ()" instead of "if()" because that is the GNU recommendation.
2010-03-26 18:47:41 +01:00
bool Cmdline::parseBool(int opt, const char *longName, const char *shortName,
bool def, Bool &value,
bool &ok)
{
string option = m_argv[opt];
string param;
size_t pos = option.find('=');
if (pos != option.npos) {
param = option.substr(pos + 1);
option.resize(pos);
}
if ((longName && boost::iequals(option, longName)) ||
(shortName && boost::iequals(option, shortName))) {
ok = true;
if (param.empty()) {
value = def;
} else if (boost::iequals(param, "t") ||
boost::iequals(param, "1") ||
boost::iequals(param, "true") ||
boost::iequals(param, "yes")) {
value = true;
} else if (boost::iequals(param, "f") ||
boost::iequals(param, "0") ||
boost::iequals(param, "false") ||
boost::iequals(param, "no")) {
value = false;
} else {
usage(true, string("parameter in '") + m_argv[opt] + "' must be 1/t/true/yes or 0/f/false/no");
ok = false;
}
// was our option
return true;
} else {
// keep searching for match
return false;
}
}
bool Cmdline::isSync()
{
// make sure command line arguments really try to run sync
if (m_usage || m_version ||
m_printServers || boost::trim_copy(m_server) == "?" ||
m_printTemplates || m_dontrun ||
m_argc == 1 || (m_useDaemon.wasSet() && m_argc == 2) ||
m_printConfig || m_remove ||
(m_server == "" && m_argc > 1) ||
m_configure || m_migrate ||
m_status || m_printSessions ||
!m_restore.empty() ||
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
m_accessItems ||
m_dryrun ||
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
(!m_run && m_props.hasProperties())) {
return false;
} else {
return true;
}
}
bool Cmdline::dontRun() const
{
// this mimics the if() checks in run()
if (m_usage || m_version ||
m_printServers || boost::trim_copy(m_server) == "?" ||
m_printTemplates) {
return false;
} else {
return m_dontrun;
}
}
2011-02-01 16:32:22 +01:00
void Cmdline::makeObsolete(boost::shared_ptr<SyncConfig> &from)
{
2011-02-01 16:32:22 +01:00
string oldname = from->getRootPath();
string newname, suffix;
int counter = 0;
while (true) {
ostringstream newsuffix;
newsuffix << ".old";
if (counter) {
newsuffix << "." << counter;
}
suffix = newsuffix.str();
newname = oldname + suffix;
if (!rename(oldname.c_str(),
newname.c_str())) {
break;
} else if (errno != EEXIST && errno != ENOTEMPTY) {
2011-02-01 16:32:22 +01:00
SE_THROW(StringPrintf("renaming %s to %s: %s",
oldname.c_str(),
newname.c_str(),
strerror(errno)));
}
counter++;
}
2011-02-01 16:32:22 +01:00
string newConfigName;
string oldContext = from->getContextName();
if (from->hasPeerProperties()) {
newConfigName = from->getPeerName() + suffix + oldContext;
} else {
newConfigName = oldContext + suffix;
}
from.reset(new SyncConfig(newConfigName));
}
void Cmdline::copyConfig(const boost::shared_ptr<SyncConfig> &from,
const boost::shared_ptr<SyncConfig> &to,
const set<string> &selectedSources)
{
const set<string> *sources = NULL;
set<string> allSources;
if (!selectedSources.empty()) {
// use explicitly selected sources
sources = &selectedSources;
} else {
// need an explicit list of all sources which will be copied,
// for the createFilters() call below
BOOST_FOREACH(const std::string &source, from->getSyncSources()) {
allSources.insert(source);
}
sources = &allSources;
}
// Apply config changes on-the-fly. Regardless what we do
// (changing an existing config, migrating, creating from
// a template), existing shared properties in the desired
// context must be preserved unless explicitly overwritten.
// Therefore read those, update with command line properties,
// then set as filter.
ConfigProps syncFilter;
SourceProps sourceFilters;
m_props.createFilters(to->getContextName(), to->getConfigName(), sources, syncFilter, sourceFilters);
from->setConfigFilter(true, "", syncFilter);
BOOST_FOREACH(const SourceProps::value_type &entry, sourceFilters) {
from->setConfigFilter(false, entry.first, entry.second);
}
// Write into the requested configuration, creating it if necessary.
to->prepareConfigForWrite();
to->copy(*from, sources);
}
void Cmdline::finishCopy(const boost::shared_ptr<SyncConfig> &from,
const boost::shared_ptr<SyncContext> &to)
{
// give a change to do something before flushing configs to files
to->preFlush(*to);
// done, now write it
m_configModified = true;
to->flush();
// migrating peer?
if (m_migrate &&
from->hasPeerProperties()) {
// also copy .synthesis dir
string fromDir, toDir;
fromDir = from->getRootPath() + "/.synthesis";
toDir = to->getRootPath() + "/.synthesis";
if (isDir(fromDir)) {
cp_r(fromDir, toDir);
}
// Succeeded so far, remove "ConsumerReady" flag from migrated
// config to hide that old config from normal UI users. Must
// do this without going through SyncConfig, because that
// would bump the version.
FileConfigNode node(from->getRootPath(), "config.ini", false);
BoolConfigProperty ready("ConsumerReady", "", "0");
if (ready.getPropertyValue(node)) {
ready.setProperty(node, false);
}
node.flush();
// Set ConsumerReady for migrated SyncEvolution < 1.2
// configs, because in older releases all existing
// configurations where shown. SyncEvolution 1.2 is more
// strict and assumes that ConsumerReady must be set
// explicitly. The sync-ui always has set the flag for
// configs created or modified with it, but the command
// line did not. Matches similar code in
// syncevo-dbus-server.
if (from->getConfigVersion(CONFIG_LEVEL_PEER, CONFIG_CUR_VERSION) == 0 /* SyncEvolution < 1.2 */) {
to->setConsumerReady(true);
to->flush();
}
}
}
void Cmdline::migratePeer(const std::string &fromPeer, const std::string &toPeer)
{
boost::shared_ptr<SyncConfig> from(new SyncConfig(fromPeer));
makeObsolete(from);
// hack: move to different target config for createSyncClient()
m_server = toPeer;
boost::shared_ptr<SyncContext> to(createSyncClient());
copyConfig(from, to, set<string>());
finishCopy(from, to);
}
/**
* Finds first instance of delimiter string in other string. In
* addition, it treats "\n\n" in a special way: that delimiter also
* matches "\n\r\n".
*/
class FindDelimiter {
const string m_delimiter;
public:
FindDelimiter(const string &delimiter) :
m_delimiter(delimiter)
{}
boost::iterator_range<string::iterator> operator()(string::iterator begin,
string::iterator end)
{
if (m_delimiter == "\n\n") {
// match both "\n\n" and "\n\r\n"
while (end - begin >= 2) {
if (*begin == '\n') {
if (*(begin + 1) == '\n') {
return boost::iterator_range<string::iterator>(begin, begin + 2);
} else if (end - begin >= 3 &&
*(begin + 1) == '\r' &&
*(begin + 2) == '\n') {
return boost::iterator_range<string::iterator>(begin, begin + 3);
}
}
++begin;
}
return boost::iterator_range<string::iterator>(end, end);
} else {
boost::sub_range<string> range(begin, end);
return boost::find_first(range, m_delimiter);
}
}
};
bool Cmdline::run() {
// --dry-run is only supported by some operations.
// Be very strict about it and make sure it is off in all
// potentially harmful operations, otherwise users might
// expect it to have an effect when it doesn't.
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// TODO: check filter properties for invalid config and source
// names
if (m_usage) {
usage(true);
} else if (m_version) {
printf("SyncEvolution %s%s\n",
VERSION,
SyncContext::isStableRelease() ? "" : " (pre-release)");
printf("%s", EDSAbiWrapperInfo());
printf("%s", SyncSource::backendsInfo().c_str());
} else if (m_printServers || boost::trim_copy(m_server) == "?") {
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
dumpConfigs("Configured servers:",
SyncConfig::getConfigs());
} else if (m_printTemplates) {
SyncConfig::DeviceList devices;
if (m_template.empty()){
dumpConfigTemplates("Available configuration templates:",
SyncConfig::getPeerTemplates(devices), false);
} else {
//limiting at templates for syncml clients only.
devices.push_back (SyncConfig::DeviceDescription("", m_template, SyncConfig::MATCH_FOR_SERVER_MODE));
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
dumpConfigTemplates("Available configuration templates:",
SyncConfig::matchPeerTemplates(devices), true);
}
} else if (m_dontrun) {
// user asked for information
command line + daemon: usability improvements (MB #5043) This patch changes what is shown to the user and how the user interacts with the command line. Details below. "--use-daemon [yes/no]" implies that yes/no is optional (square brackets!), with "yes" being the option that could be expected for a plain "--use-daemon" parameter. But the implementation always expects a "yes" or "no" parameter. The original format suggested was "--use-daemon[=yes/no]" This patch switches to that format, changes --use-daemon into --daemon (to be consistent with --keyring) and enables the same format for --keyring. Although not documented, 0/f/false and 1/t/true are also accepted. Because the value becomes part of the parameter, m_argc checks had to be adapted. The documentation for "--use-daemon" was inserted in the middle of the "--keyring documentation". "Parameter not set" has to be available to the Cmdline caller in the command line too, in addition to true/false. This was done originally with a string which is empty, "yes" or "no". Using a tri-state Cmdline::Bool class makes this a bit more explicit and removes the ambiguity around what useDaemon() returns (values weren't documented). When running without --daemon and no daemon available, the first lines of output were: ERROR: org.<cryptic error> [INFO] itodo20: inactive .... => The command line should fall back *silently* to running in-process. => Error messages should be formatted and logged as such, using SE_LOG_ERROR(). Old code might not have done that and we need to preserve that for compatibility with frontends, but new code should use [ERROR] as output. => D-Bus error messages (as in the case above) must have some user (and developer!) comprehensible explanation what went wrong. The D-Bus error class itself is no enough. Although I haven't tested it, I suspect that the code also would have re-run the operation in-process after the D-Bus server already executed it and failed. I rewrote this so that a check for "daemon available" without error messages is done first before committing to using the daemon. Once that decision is made, the command line will not fall back to in-process execution. Rewrote several error messages. Telling a user of a distro's binary to "re-configure" is misleading (he didn't configure himself). "can't" => "cannot", punctuation changes. Not sure whether is always an improvement, comments welcome. Comment on coding style: I've used "if ()" instead of "if()" because that is the GNU recommendation.
2010-03-26 18:47:41 +01:00
} else if (m_argc == 1 || (m_useDaemon.wasSet() && m_argc == 2)) {
// no parameters: list databases and short usage
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
const SourceRegistry &registry(SyncSource::getSourceRegistry());
config: reorganized for shared config layout (MB#7707) This patch introduces code changes for the new layout without actually using it yet. Therefore all existing tests for the older layout still pass. The new meaning of the former "server name" is introduced: - A plain string now refers to a peer configuration (can be client or server). - The @ sign allows selecting a specific context. Different contexts have independent sets of local sources and peer definitions. - An empty peer name selects a view on the configuration which contains no peer-specific properties. Not fully implemented yet. The FileConfigTree is instantiated with a root which is one level high up compare to before this patch (for example, "~/.config/syncevolution" instead of "./config/syncevolution/scheduleworld") and then config files include that dropped level in their relative path name ("scheduleworld/config.ini" instead of "config.ini"). This allows accessing the global properties in "~/.config/syncevolution/config.ini" and will be used to move peers further down the hierarchy ("~/.config/syncevolution/peers/scheduleworld/config.ini"). To keep the output of "--print-servers" consistent, the FileConfigTree gets another parameter which identifies the subset of the larger tree that is referenced by this FileConfigTree instance. One side effect of this change is that FileConfigTree instances are no longer completely separate. Something to keep in mind when instantiating SyncContext multiple times (MB#8006). Code may no longer make assumptions in which config node a property is stored. This is determined by the new getNode() calls based on the property attributes (hidden, sharing). The new layout is represented as a set of config nodes. Older layouts use the same set of nodes with identical instances assigned to them, if they don't really have separate files for each of them. SyncSourceNodes no longer grants direct access to the nodes, to catch code which incorrectly access a specific node directly. For the same reason the name of the nodes changed. Code which needs access to all hidden or all visible properties now does this via a config node returned by getProperties(). Currently this is identical to the underlying nodes. Once the new layout is active, this node will act as a multiplexer which gathers properties from all underlying nodes when reading and picks the right one when writing. The "change ID" parameter for sources has been obsolete for a while and was removed. Reorganized the property registration so that it is a bit easier to see which properties are hidden and which use non-default sharing. The default sharing is "no sharing". Some other code was improved while touching it: - removed useless visibility[] array in favor of a i != 0 check in SyncConfig::copy() - added default parameters to save/checkPassword() methods - some constness definition changes - Property::getProperty() is a virtual call which could only be overloaded in one case because the constness was wrong; now getProperty() always returns the string value and getPropertyValue() some other kind of representation of it, depending on the class. - ConstSyncSourceNodes is based on SyncSourceNodes instead of duplicating it, which simplifies the implementation. The simplified SyncSourceAdmin API changed slightly: instead of passing a pointer to the source's SyncSourceNodes, the default nodes are now found via the SyncSource pointer. For callers this is a bit less work and it is more general.
2009-11-13 14:52:00 +01:00
boost::shared_ptr<FilterConfigNode> sharedNode(new VolatileConfigNode());
boost::shared_ptr<FilterConfigNode> configNode(new VolatileConfigNode());
boost::shared_ptr<FilterConfigNode> hiddenNode(new VolatileConfigNode());
boost::shared_ptr<FilterConfigNode> trackingNode(new VolatileConfigNode());
boost::shared_ptr<FilterConfigNode> serverNode(new VolatileConfigNode());
SyncSourceNodes nodes(true, sharedNode, configNode, hiddenNode, trackingNode, serverNode, "");
SyncSourceParams params("list", nodes, boost::shared_ptr<const SyncConfig>());
BOOST_FOREACH(const RegisterSyncSource *source, registry) {
BOOST_FOREACH(const Values::value_type &alias, source->m_typeValues) {
if (!alias.empty() && source->m_enabled) {
configNode->setProperty("type", *alias.begin());
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
auto_ptr<SyncSource> source(SyncSource::createSource(params, false));
if (source.get() != NULL) {
listSources(*source, boost::join(alias, " = "));
m_out << "\n";
}
}
}
}
usage(false);
} else if (m_printConfig) {
boost::shared_ptr<SyncConfig> config;
ConfigProps syncFilter;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
SourceProps sourceFilters;
if (m_template.empty()) {
if (m_server.empty()) {
m_err << "ERROR: --print-config requires either a --template or a server name." << endl;
return false;
}
config.reset(new SyncConfig(m_server));
if (!config->exists()) {
m_err << "ERROR: server '" << m_server << "' has not been configured yet." << endl;
return false;
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// No need to include a context or additional sources,
// because reading the m_server config already includes
// the right information.
m_props.createFilters("", m_server, NULL, syncFilter, sourceFilters);
} else {
string peer, context;
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_template), peer, context);
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
config = SyncConfig::createPeerTemplate(peer);
if (!config.get()) {
m_err << "ERROR: no configuration template for '" << m_template << "' available." << endl;
return false;
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// When instantiating a template, include the properties
// of the target context as filter to preserve shared
// properties, the final name inside that context as
// peer config name, and the sources defined in the template.
list<string> sourcelist = config->getSyncSources();
set<string> sourceset(sourcelist.begin(), sourcelist.end());
m_props.createFilters(std::string("@") + context, "",
&sourceset,
syncFilter, sourceFilters);
}
// determine whether we dump a peer or a context
int flags = DUMP_PROPS_NORMAL;
string peer, context;
SyncConfig::splitConfigString(config->getConfigName(), peer, context);
if (peer.empty()) {
flags |= HIDE_PER_PEER;
checkForPeerProps();
}
if (m_sources.empty() ||
m_sources.find("main") != m_sources.end()) {
boost::shared_ptr<FilterConfigNode> syncProps(config->getProperties());
syncProps->setFilter(syncFilter);
dumpProperties(*syncProps, config->getRegistry(), flags);
}
list<string> sources = config->getSyncSources();
sources.sort();
BOOST_FOREACH(const string &name, sources) {
if (m_sources.empty() ||
m_sources.find(name) != m_sources.end()) {
m_out << endl << "[" << name << "]" << endl;
config: reorganized for shared config layout (MB#7707) This patch introduces code changes for the new layout without actually using it yet. Therefore all existing tests for the older layout still pass. The new meaning of the former "server name" is introduced: - A plain string now refers to a peer configuration (can be client or server). - The @ sign allows selecting a specific context. Different contexts have independent sets of local sources and peer definitions. - An empty peer name selects a view on the configuration which contains no peer-specific properties. Not fully implemented yet. The FileConfigTree is instantiated with a root which is one level high up compare to before this patch (for example, "~/.config/syncevolution" instead of "./config/syncevolution/scheduleworld") and then config files include that dropped level in their relative path name ("scheduleworld/config.ini" instead of "config.ini"). This allows accessing the global properties in "~/.config/syncevolution/config.ini" and will be used to move peers further down the hierarchy ("~/.config/syncevolution/peers/scheduleworld/config.ini"). To keep the output of "--print-servers" consistent, the FileConfigTree gets another parameter which identifies the subset of the larger tree that is referenced by this FileConfigTree instance. One side effect of this change is that FileConfigTree instances are no longer completely separate. Something to keep in mind when instantiating SyncContext multiple times (MB#8006). Code may no longer make assumptions in which config node a property is stored. This is determined by the new getNode() calls based on the property attributes (hidden, sharing). The new layout is represented as a set of config nodes. Older layouts use the same set of nodes with identical instances assigned to them, if they don't really have separate files for each of them. SyncSourceNodes no longer grants direct access to the nodes, to catch code which incorrectly access a specific node directly. For the same reason the name of the nodes changed. Code which needs access to all hidden or all visible properties now does this via a config node returned by getProperties(). Currently this is identical to the underlying nodes. Once the new layout is active, this node will act as a multiplexer which gathers properties from all underlying nodes when reading and picks the right one when writing. The "change ID" parameter for sources has been obsolete for a while and was removed. Reorganized the property registration so that it is a bit easier to see which properties are hidden and which use non-default sharing. The default sharing is "no sharing". Some other code was improved while touching it: - removed useless visibility[] array in favor of a i != 0 check in SyncConfig::copy() - added default parameters to save/checkPassword() methods - some constness definition changes - Property::getProperty() is a virtual call which could only be overloaded in one case because the constness was wrong; now getProperty() always returns the string value and getPropertyValue() some other kind of representation of it, depending on the class. - ConstSyncSourceNodes is based on SyncSourceNodes instead of duplicating it, which simplifies the implementation. The simplified SyncSourceAdmin API changed slightly: instead of passing a pointer to the source's SyncSourceNodes, the default nodes are now found via the SyncSource pointer. For callers this is a bit less work and it is more general.
2009-11-13 14:52:00 +01:00
SyncSourceNodes nodes = config->getSyncSourceNodes(name);
boost::shared_ptr<FilterConfigNode> sourceProps = nodes.getProperties();
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
sourceProps->setFilter(sourceFilters.createSourceFilter(name));
dumpProperties(*sourceProps, SyncSourceConfig::getRegistry(),
flags | ((name != *(--sources.end())) ? HIDE_LEGEND : DUMP_PROPS_NORMAL));
}
}
} else if (m_server == "" && m_argc > 1) {
// Options given, but no server - not sure what the user wanted?!
usage(true, "server name missing");
return false;
} else if (m_configure || m_migrate) {
if (m_dryrun) {
SyncContext::throwError("--dry-run not supported for configuration changes");
}
if (m_keyring) {
#ifndef USE_GNOME_KEYRING
m_err << "Error: this syncevolution binary was compiled without support for storing "
"passwords in a keyring. Either store passwords in your configuration "
"files or enter them interactively on each program run." << endl;
return false;
#endif
}
// name of renamed config ("foo.old") after migration
string newname;
// True if the target configuration is a context like @default
// or @foobar. Relevant in several places in the following
// code.
bool configureContext = false;
bool fromScratch = false;
string peer, context;
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_server), peer, context);
if (peer.empty()) {
configureContext = true;
checkForPeerProps();
}
// Make m_server a fully-qualified name. Useful in error
// messages and essential for migrating "foo" where "foo"
// happens to map to "foo@bar". Otherwise "foo" will be
// mapped incorrectly to "foo@default" after renaming
// "foo@bar" to "foo.old@bar".
//
// The inverse problem can occur for "foo@default": after
// renaming, "foo" without "@default" would be mapped to
// "foo@somewhere-else" if such a config exists.
m_server = peer + "@" + context;
// Both config changes and migration are implemented as copying from
// another config (template resp. old one). Migration also moves
// the old config.
boost::shared_ptr<SyncConfig> from;
string origPeer;
if (m_migrate) {
if (!m_sources.empty()) {
m_err << "ERROR: cannot migrate individual sources" << endl;
return false;
}
string oldContext = context;
from.reset(new SyncConfig(m_server));
if (!from->exists()) {
// for migration into a different context, search for config without context
oldContext = "";
from.reset(new SyncConfig(peer));
if (!from->exists()) {
m_err << "ERROR: server '" << m_server << "' has not been configured yet." << endl;
return false;
}
}
// Check if we are migrating an individual peer inside
// a context which itself is too old. In that case,
// the whole context and everything inside it needs to
// be migrated.
if (!configureContext) {
bool obsoleteContext = false;
if (from->getLayout() < SyncConfig::SHARED_LAYOUT) {
// check whether @default context exists and is too old;
// in that case migrate it first
SyncConfig target("@default");
if (target.exists() &&
target.getConfigVersion(CONFIG_LEVEL_CONTEXT, CONFIG_CUR_VERSION) <
CONFIG_CONTEXT_MIN_VERSION) {
// migrate all peers inside @default *and* the one outside
origPeer = m_server;
m_server = "@default";
obsoleteContext = true;
}
} else {
// config already is inside a context; need to check that context
if (from->getConfigVersion(CONFIG_LEVEL_CONTEXT, CONFIG_CUR_VERSION) <
CONFIG_CONTEXT_MIN_VERSION) {
m_server = string("@") + context;
obsoleteContext = true;
}
}
if (obsoleteContext) {
// hack: move to different config and back later
from.reset(new SyncConfig(m_server));
peer = "";
configureContext = true;
}
}
2011-02-01 16:32:22 +01:00
// rename on disk and point "from" to it
makeObsolete(from);
} else {
from.reset(new SyncConfig(m_server));
if (!from->exists()) {
// creating from scratch, look for template
fromScratch = true;
string configTemplate;
if (m_template.empty()) {
// template is the peer name
configTemplate = m_server;
if (configureContext) {
// configuring a context, template doesn't matter =>
// use default "SyncEvolution" template
configTemplate =
peer = "SyncEvolution";
}
} else {
// Template is specified explicitly. It must not contain a context,
// because the context comes from the config name.
configTemplate = m_template;
if (SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(configTemplate), peer, context)) {
m_err << "ERROR: template " << configTemplate << " must not specify a context." << endl;
return false;
}
string tmp;
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(m_server), tmp, context);
}
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
from = SyncConfig::createPeerTemplate(peer);
if (!from.get()) {
m_err << "ERROR: no configuration template for '" << configTemplate << "' available." << endl;
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
dumpConfigTemplates("Available configuration templates:",
SyncConfig::getPeerTemplates(SyncConfig::DeviceList()));
return false;
}
if (!from->getPeerIsClient()) {
// Templates no longer contain these strings, because
// GUIs would have to localize them. For configs created
// via the command line, the extra hint that these
// properties need to be set is useful, so set these
// strings here. They'll get copied into the new
// config only if no other value was given on the
// command line.
if (!from->getUsername()[0]) {
from->setUsername("your SyncML server account name");
}
if (!from->getPassword()[0]) {
from->setPassword("your SyncML server password");
}
} else {
// uncomment SyncURL, so that it can be shown by
// sync-ui
if (from->getSyncURL().size() == 0) {
from->setSyncURL ("input your peer address here");
}
}
}
}
// Which sources are configured is determined as follows:
// - all sources in the template by default (empty set), except when
// - sources are listed explicitly, and either
// - updating an existing config or
// - configuring a context.
//
// This implies that when configuring a peer from scratch, all
// sources in the template will be created, with command line
// source properties applied to all of them. This might not be
// what we want, but because this is how we have done it
// traditionally, I keep this behavior for now.
//
// When migrating, m_sources is empty and thus the whole set of
// sources will be migrated. Checking it here for clarity's sake.
set<string> sources;
if (!m_migrate &&
!m_sources.empty() &&
(!fromScratch || configureContext)) {
sources = m_sources;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
}
// copy and filter into the target config: createSyncClient()
// creates a SyncContext for m_server, with propert
// implementation of the password handling methods in derived
// classes (D-Bus server, real command line)
boost::shared_ptr<SyncContext> to(createSyncClient());
copyConfig(from, to, sources);
// Sources are active now according to the server default.
// Disable all sources not selected by user (if any selected)
// and those which have no database.
if (fromScratch) {
list<string> configuredSources = to->getSyncSources();
set<string> sources = m_sources;
BOOST_FOREACH(const string &source, configuredSources) {
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
boost::shared_ptr<PersistentSyncSourceConfig> sourceConfig(to->getSyncSourceConfig(source));
string disable = "";
set<string>::iterator entry = sources.find(source);
bool selected = entry != sources.end();
if (!m_sources.empty() &&
!selected) {
disable = "not selected";
} else {
if (entry != sources.end()) {
// The command line parameter matched a valid source.
// All entries left afterwards must have been typos.
sources.erase(entry);
}
// check whether the sync source works
SyncSourceParams params("list", to->getSyncSourceNodes(source), to);
auto_ptr<SyncSource> syncSource(SyncSource::createSource(params, false, to.get()));
if (syncSource.get() == NULL) {
disable = "no backend available";
} else {
try {
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
SyncSource::Databases databases = syncSource->getDatabases();
if (databases.empty()) {
disable = "no database to synchronize";
}
} catch (...) {
disable = "backend failed";
}
}
}
// Do sanity checking of source (can it be enabled?),
// but only set the sync mode if configuring a peer.
// A context-only config doesn't have the "sync"
// property.
string syncMode;
if (!disable.empty()) {
// abort if the user explicitly asked for the sync source
// and it cannot be enabled, otherwise disable it silently
if (selected) {
SyncContext::throwError(source + ": " + disable);
}
syncMode = "disabled";
} else if (selected) {
// user absolutely wants it: enable even if off by default
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
ConfigProps filter = m_props.createSourceFilter(m_server, source);
ConfigProps::const_iterator sync = filter.find("sync");
syncMode = sync == filter.end() ? "two-way" : sync->second;
}
if (!syncMode.empty() &&
!configureContext) {
sourceConfig->setSync(syncMode);
}
}
if (!sources.empty()) {
SyncContext::throwError(string("no such source(s): ") + boost::join(sources, " "));
}
}
// flush, move .synthesis dir, set ConsumerReady, ...
finishCopy(from, to);
// Now also migrate all peers inside context?
if (configureContext && m_migrate) {
BOOST_FOREACH(const string &peer, from->getPeers()) {
migratePeer(peer + from->getContextName(), peer + to->getContextName());
}
if (!origPeer.empty()) {
migratePeer(origPeer, origPeer + to->getContextName());
}
}
} else if (m_remove) {
if (m_dryrun) {
SyncContext::throwError("--dry-run not supported for removing configurations");
}
// extra sanity check
if (!m_sources.empty() ||
m_props.hasProperties()) {
usage(true, "too many parameters for --remove");
return false;
} else {
boost::shared_ptr<SyncConfig> config;
config.reset(new SyncConfig(m_server));
if (!config->exists()) {
SyncContext::throwError(string("no such configuration: ") + m_server);
}
config->remove();
m_configModified = true;
return true;
}
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
} else if (m_accessItems) {
// need access to specific source
boost::shared_ptr<SyncContext> context;
context.reset(createSyncClient());
context->setOutput(&m_out);
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// operating on exactly one source
string sourceName = *m_sources.begin();
// apply filters
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
context->setConfigFilter(true, "", m_props.createSyncFilter(m_server));
context->setConfigFilter(false, "", m_props.createSourceFilter(m_server, sourceName));
SyncSourceNodes sourceNodes = context->getSyncSourceNodesNoTracking(sourceName);
SyncSourceParams params(sourceName, sourceNodes, context);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
cxxptr<SyncSource> source(SyncSource::createSource(params, true));
sysync::TSyError err;
#define CHECK_ERROR(_op) if (err) { SE_THROW_EXCEPTION_STATUS(StatusException, string(source->getName()) + ": " + (_op), SyncMLStatus(err)); }
source->open();
const SyncSource::Operations &ops = source->getOperations();
if (m_printItems) {
SyncSourceLogging *logging = dynamic_cast<SyncSourceLogging *>(source.get());
if (!ops.m_startDataRead ||
!ops.m_readNextItem) {
source->throwError("reading items not supported");
}
err = ops.m_startDataRead("", "");
CHECK_ERROR("reading items");
list<string> luids;
readLUIDs(source, luids);
BOOST_FOREACH(string &luid, luids) {
string description;
if (logging) {
description = logging->getDescription(luid);
if (!description.empty()) {
description.insert(0, ": ");
}
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
}
m_out << CmdlineLUID::fromLUID(luid) << description << std::endl;
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
}
} else if (m_deleteItems) {
if (!ops.m_deleteItem) {
source->throwError("deleting items not supported");
}
list<string> luids;
bool deleteAll = std::find(m_luids.begin(), m_luids.end(), "*") != m_luids.end();
err = ops.m_startDataRead("", "");
CHECK_ERROR("reading items");
if (deleteAll) {
readLUIDs(source, luids);
} else {
luids = m_luids;
}
if (ops.m_endDataRead) {
err = ops.m_endDataRead();
CHECK_ERROR("stop reading items");
}
if (ops.m_startDataWrite) {
err = ops.m_startDataWrite();
CHECK_ERROR("writing items");
}
BOOST_FOREACH(const string &luid, luids) {
sysync::ItemIDType id;
id.item = (char *)luid.c_str();
err = ops.m_deleteItem(&id);
CHECK_ERROR("deleting item");
}
char *token;
err = ops.m_endDataWrite(true, &token);
if (token) {
free(token);
}
CHECK_ERROR("stop writing items");
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
} else {
SyncSourceRaw *raw = dynamic_cast<SyncSourceRaw *>(source.get());
if (!raw) {
source->throwError("reading/writing items directly not supported");
}
if (m_import || m_update) {
err = ops.m_startDataRead("", "");
CHECK_ERROR("reading items");
if (ops.m_endDataRead) {
err = ops.m_endDataRead();
CHECK_ERROR("stop reading items");
}
if (ops.m_startDataWrite) {
err = ops.m_startDataWrite();
CHECK_ERROR("writing items");
}
cxxptr<ifstream> inFile;
if (m_itemPath =="-" ||
!isDir(m_itemPath)) {
string content;
string luid;
if (m_itemPath == "-") {
context->readStdin(content);
} else if (!ReadFile(m_itemPath, content)) {
SyncContext::throwError(m_itemPath, errno);
}
if (m_delimiter == "none") {
if (m_update) {
if (m_luids.size() != 1) {
SyncContext::throwError("need exactly one LUID parameter");
} else {
luid = *m_luids.begin();
}
}
m_out << "#0: "
<< insertItem(raw, luid, content).getEncoded()
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
<< endl;
} else {
typedef boost::split_iterator<string::iterator> string_split_iterator;
int count = 0;
FindDelimiter finder(m_delimiter);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
// when updating, check number of luids in advance
if (m_update) {
unsigned long total = 0;
for (string_split_iterator it =
boost::make_split_iterator(content, finder);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
it != string_split_iterator();
++it) {
total++;
}
if (total != m_luids.size()) {
SyncContext::throwError(StringPrintf("%lu items != %lu luids, must match => aborting",
total, (unsigned long)m_luids.size()));
}
}
list<string>::const_iterator luidit = m_luids.begin();
for (string_split_iterator it =
boost::make_split_iterator(content, finder);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
it != string_split_iterator();
++it) {
m_out << "#" << count << ": ";
string luid;
if (m_update) {
if (luidit == m_luids.end()) {
// was checked above
SyncContext::throwError("internal error, not enough luids");
}
luid = *luidit;
++luidit;
}
m_out << insertItem(raw,
luid,
string(it->begin(), it->end())).getEncoded()
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
<< endl;
count++;
}
}
} else {
ReadDir dir(m_itemPath);
int count = 0;
BOOST_FOREACH(const string &entry, dir) {
string content;
string path = m_itemPath + "/" + entry;
m_out << count << ": " << entry << ": ";
if (!ReadFile(path, content)) {
SyncContext::throwError(path, errno);
}
m_out << insertItem(raw, "", content).getEncoded() << endl;
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
}
}
char *token = NULL;
err = ops.m_endDataWrite(true, &token);
if (token) {
free(token);
}
CHECK_ERROR("stop writing items");
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
} else if (m_export) {
err = ops.m_startDataRead("", "");
CHECK_ERROR("reading items");
ostream *out = NULL;
cxxptr<ofstream> outFile;
if (m_itemPath == "-") {
out = &m_out;
} else if(!isDir(m_itemPath)) {
outFile.set(new ofstream(m_itemPath.c_str()));
out = outFile;
}
if (m_luids.empty()) {
readLUIDs(source, m_luids);
}
bool haveItem = false; // have written one item
bool haveNewline = false; // that item had a newline at the end
try {
BOOST_FOREACH(const string &luid, m_luids) {
string item;
raw->readItemRaw(luid, item);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
if (!out) {
// write into directory
string fullPath = m_itemPath + "/" + luid;
ofstream file((m_itemPath + "/" + luid).c_str());
file << item;
file.close();
if (file.bad()) {
SyncContext::throwError(fullPath, errno);
}
} else {
if (haveItem) {
if (m_delimiter.size() > 1 &&
haveNewline &&
m_delimiter[0] == '\n') {
// already wrote initial newline, skip it
*out << m_delimiter.substr(1);
} else {
*out << m_delimiter;
}
}
*out << item;
haveNewline = !item.empty() && item[item.size() - 1] == '\n';
haveItem = true;
}
}
} catch (...) {
// ensure that we start following output on new line
if (m_itemPath == "-" && haveItem && !haveNewline) {
m_out << endl;
}
throw;
}
if (outFile) {
outFile->close();
if (outFile->bad()) {
SyncContext::throwError(m_itemPath, errno);
}
}
}
}
source->close();
} else {
std::set<std::string> unmatchedSources;
boost::shared_ptr<SyncContext> context;
context.reset(createSyncClient());
context->setConfigProps(m_props);
context->setQuiet(m_quiet);
context->setDryRun(m_dryrun);
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
context->setConfigFilter(true, "", m_props.createSyncFilter(m_server));
context->setOutput(&m_out);
if (m_sources.empty()) {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// Special semantic of 'no source selected': apply
// filter (if any exists) only to sources which are
// *active*. Configuration of inactive sources is left
// unchanged. This way we don't activate sync sources
// accidentally when the sync mode is modified
// temporarily.
BOOST_FOREACH(const std::string &source,
context->getSyncSources()) {
boost::shared_ptr<PersistentSyncSourceConfig> source_config =
context->getSyncSourceConfig(source);
if (source_config->getSync() != "disabled") {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
context->setConfigFilter(false, source, m_props.createSourceFilter(m_server, source));
}
}
} else {
// apply (possibly empty) source filter to selected sources
BOOST_FOREACH(const std::string &source,
m_sources) {
boost::shared_ptr<PersistentSyncSourceConfig> source_config =
context->getSyncSourceConfig(source);
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
ConfigProps filter = m_props.createSourceFilter(m_server, source);
if (!source_config || !source_config->exists()) {
// invalid source name in m_sources, remember and
// report this below
unmatchedSources.insert(source);
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
} else if (filter.find("sync") == filter.end()) {
// Sync mode is not set, must override the
// "sync=disabled" set below with the original
// sync mode for the source or (if that is also
// "disabled") with "two-way". The latter is part
// of the command line semantic that listing a
// source activates it.
string sync = source_config->getSync();
filter["sync"] =
sync == "disabled" ? "two-way" : sync;
context->setConfigFilter(false, source, filter);
} else {
// sync mode is set, can use m_sourceProps
// directly to apply it
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
context->setConfigFilter(false, source, filter);
}
}
// temporarily disable the rest
FilterConfigNode::ConfigFilter disabled;
disabled["sync"] = "disabled";
context->setConfigFilter(false, "", disabled);
}
// check whether there were any sources specified which do not exist
if (unmatchedSources.size()) {
context->throwError(string("no such source(s): ") + boost::join(unmatchedSources, " "));
}
if (m_status) {
context->status();
} else if (m_printSessions) {
vector<string> dirs;
context->getSessions(dirs);
bool first = true;
BOOST_FOREACH(const string &dir, dirs) {
if (first) {
first = false;
} else if(!m_quiet) {
m_out << endl;
}
m_out << dir << endl;
if (!m_quiet) {
SyncReport report;
context->readSessionInfo(dir, report);
m_out << report;
}
}
} else if (!m_restore.empty()) {
// sanity checks: either --after or --before must be given, sources must be selected
if ((!m_after && !m_before) ||
(m_after && m_before)) {
usage(false, "--restore <log dir> must be used with either --after (restore database as it was after that sync) or --before (restore data from before sync)");
return false;
}
if (m_sources.empty()) {
usage(false, "Sources must be selected explicitly for --restore to prevent accidental restore.");
return false;
}
context->restore(m_restore,
m_after ?
SyncContext::DATABASE_AFTER_SYNC :
SyncContext::DATABASE_BEFORE_SYNC);
} else {
if (m_dryrun) {
SyncContext::throwError("--dry-run not supported for running a synchronization");
}
// safety catch: if props are given, then --run
// is required
if (!m_run &&
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
(m_props.hasProperties())) {
usage(false, "Properties specified, but neither '--configure' nor '--run' - what did you want?");
return false;
}
return (context->sync(&m_report) == STATUS_OK);
}
}
return true;
}
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
void Cmdline::readLUIDs(SyncSource *source, list<string> &luids)
{
const SyncSource::Operations &ops = source->getOperations();
sysync::ItemIDType id;
sysync::sInt32 status;
sysync::TSyError err = ops.m_readNextItem(&id, &status, true);
CHECK_ERROR("next item");
while (status != sysync::ReadNextItem_EOF) {
luids.push_back(id.item);
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
err = ops.m_readNextItem(&id, &status, false);
CHECK_ERROR("next item");
}
}
CmdlineLUID Cmdline::insertItem(SyncSourceRaw *source, const string &luid, const string &data)
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
{
SyncSourceRaw::InsertItemResult res = source->insertItemRaw(luid, data);
CmdlineLUID cluid;
cluid.setLUID(res.m_luid);
return cluid;
command line: added --import/export/update/print-items These operations provide a common interface for manipulating databases supported by SyncEvolution backends. --delete is an obvious gap, will be added soon. The implementation supports all backends offering the SyncSourceRaw interface (Evolution, Akonadi, XMLRPC, file, but not the sqlite demo), which is determined via a dynamic cast. SyncSourceRaw is necessary because it allows direct access to the native data format without going through the Synthesis engine. Because the Synthesis engine is not activated, printing the short description (SyncSourceLogging interface) mentioned in the README.rst is not possible yet. Having such an engine would be useful also for importing/exporting data which is not in the native format of the backend; additional command line parameters will be needed to define that format. All of the new operations have in common that they work on one source and multiple LUIDs. This is a slight deviation from other command line synopsises where all arguments after the server config refer to sources. The new m_accessItems flag is set for these special operations; they also share much of the setup code. The implementation itself tries to use the generic SyncSource interface as much as possible. It only falls back to more specialized implementations where necessary (SyncSourceRaw). The builtin synopsis and usage was intentionally not updated. The expection is that before this patch lands in the "master" branch, the builtin text will come directly from README.rst (which was updated).
2010-06-11 15:44:57 +02:00
}
string Cmdline::cmdOpt(const char *opt, const char *param)
{
string res = "'";
res += opt;
if (param) {
res += " ";
res += param;
}
res += "'";
return res;
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
bool Cmdline::parseProp(PropertyType propertyType,
const char *opt,
const char *param,
const char *propname)
{
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
std::string args = cmdOpt(opt, param);
if (!param) {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
usage(true, string("missing parameter for ") + args);
return false;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
}
// determine property name and parameter for it
string propstr;
string paramstr;
if (propname) {
propstr = propname;
paramstr = param;
} else if (boost::trim_copy(string(param)) == "?") {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
paramstr = param;
} else {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
const char *equal = strchr(param, '=');
if (!equal) {
usage(true, string("the '=<value>' part is missing in: ") + args);
return false;
}
propstr.assign(param, equal - param);
paramstr.assign(equal + 1);
}
boost::trim(propstr);
boost::trim_left(paramstr);
// parse full property string
PropertySpecifier spec = PropertySpecifier::StringToPropSpec(propstr);
// determine property type and registry
const ConfigPropertyRegistry *validProps = NULL;
switch (propertyType) {
case SYNC_PROPERTY_TYPE:
validProps = &m_validSyncProps;
break;
case SOURCE_PROPERTY_TYPE:
validProps = &m_validSourceProps;
break;
case UNKNOWN_PROPERTY_TYPE:
// must guess based on both registries
if (!propstr.empty()) {
bool isSyncProp = m_validSyncProps.find(spec.m_property) != NULL;
bool isSourceProp = m_validSourceProps.find(spec.m_property) != NULL;
if (isSyncProp) {
if (isSourceProp) {
usage(true, StringPrintf("property '%s' in %s could be both a sync and a source property, use --sync-property or --source-property to disambiguate it", propname, args.c_str()));
return false;
} else {
validProps = &m_validSyncProps;
}
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
} else if (isSourceProp ||
boost::iequals(spec.m_property, "type")) {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
validProps = &m_validSourceProps;
} else {
usage(true, StringPrintf("unrecognized property '%s' in %s", propname, args.c_str()));
return false;
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
} else {
usage(true, StringPrintf("a property name must be given in '%s'", args.c_str()));
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
if (boost::trim_copy(string(param)) == "?") {
m_dontrun = true;
if (propname) {
return listPropValues(*validProps, spec.m_property, opt);
} else {
return listProperties(*validProps, opt);
}
} else {
if (boost::trim_copy(paramstr) == "?") {
m_dontrun = true;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
return listPropValues(*validProps, spec.m_property, cmdOpt(opt, param));
} else {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
const ConfigProperty *prop = validProps->find(spec.m_property);
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
if (!prop && boost::iequals(spec.m_property, "type")) {
// compatiblity mode for "type": map to the properties which
// replaced it
prop = validProps->find("backend");
if (!prop) {
m_err << "ERROR: backend: no such property" << endl;
return false;
}
SourceType sourceType(paramstr);
string error;
if (!prop->checkValue(sourceType.m_backend, error)) {
m_err << "ERROR: " << args << ": " << error << endl;
return false;
}
ContextProps &props = m_props[spec.m_config];
props.m_sourceProps[spec.m_source]["backend"] = sourceType.m_backend;
props.m_sourceProps[spec.m_source]["databaseFormat"] = sourceType.m_localFormat;
props.m_sourceProps[spec.m_source]["syncFormat"] = sourceType.m_format;
props.m_sourceProps[spec.m_source]["forceSyncFormat"] = sourceType.m_forceFormat ? "1" : "0";
return true;
} else if (!prop) {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
m_err << "ERROR: " << args << ": no such property" << endl;
return false;
} else {
string error;
if (!prop->checkValue(paramstr, error)) {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
m_err << "ERROR: " << args << ": " << error << endl;
return false;
} else {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
ContextProps &props = m_props[spec.m_config];
if (validProps == &m_validSyncProps) {
// complain if sync property includes source prefix
if (!spec.m_source.empty()) {
m_err << "ERROR: " << args << ": source name '" << spec.m_source << "' not allowed in sync property" << endl;
return false;
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
props.m_syncProps[spec.m_property] = paramstr;
} else {
props.m_sourceProps[spec.m_source][spec.m_property] = paramstr;
}
return true;
}
}
}
}
}
bool Cmdline::listPropValues(const ConfigPropertyRegistry &validProps,
const string &propName,
const string &opt)
{
const ConfigProperty *prop = validProps.find(propName);
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
if (!prop && boost::iequals(propName, "type")) {
m_out << opt << endl;
m_out << " <backend>[:<format>[:<version][!]]" << endl;
m_out << " legacy property, replaced by 'backend', 'databaseFormat'," << endl;
m_out << " 'syncFormat', 'forceSyncFormat'" << endl;
return true;
} else if (!prop) {
m_err << "ERROR: "<< opt << ": no such property" << endl;
return false;
} else {
m_out << opt << endl;
string comment = prop->getComment();
if (comment != "") {
list<string> commentLines;
ConfigProperty::splitComment(comment, commentLines);
BOOST_FOREACH(const string &line, commentLines) {
m_out << " " << line << endl;
}
} else {
m_out << " no documentation available" << endl;
}
return true;
}
}
bool Cmdline::listProperties(const ConfigPropertyRegistry &validProps,
const string &opt)
{
// The first of several related properties has a comment.
// Remember that comment and print it as late as possible,
// that way related properties preceed their comment.
string comment;
BOOST_FOREACH(const ConfigProperty *prop, validProps) {
if (!prop->isHidden()) {
string newComment = prop->getComment();
if (newComment != "") {
if (!comment.empty()) {
dumpComment(m_out, " ", comment);
m_out << endl;
}
comment = newComment;
}
m_out << prop->getMainName() << ":" << endl;
}
}
dumpComment(m_out, " ", comment);
return true;
}
static void findPeerProps(FilterConfigNode::ConfigFilter &filter,
ConfigPropertyRegistry &registry,
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
set<string> &peerProps)
{
BOOST_FOREACH(StringPair entry, filter) {
const ConfigProperty *prop = registry.find(entry.first);
if (prop &&
prop->getSharing() == ConfigProperty::NO_SHARING) {
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
peerProps.insert(entry.first);
}
}
}
void Cmdline::checkForPeerProps()
{
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
set<string> peerProps;
BOOST_FOREACH(FullProps::value_type &entry, m_props) {
ContextProps &props = entry.second;
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
findPeerProps(props.m_syncProps, SyncConfig::getRegistry(), peerProps);
BOOST_FOREACH(SourceProps::value_type &entry, props.m_sourceProps) {
findPeerProps(entry.second, SyncSourceConfig::getRegistry(), peerProps);
}
}
if (!peerProps.empty()) {
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
string props = boost::join(peerProps, ", ");
if (props == "forceSyncFormat, syncFormat") {
// special case: these two properties might have been added by the
// legacy "sync" property, which applies to both shared and unshared
// properties => cannot determine that here anymore, so ignore it
} else {
SyncContext::throwError(string("per-peer (unshared) properties not allowed: ") +
props);
}
}
}
void Cmdline::listSources(SyncSource &syncSource, const string &header)
{
m_out << header << ":\n";
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
SyncSource::Databases databases = syncSource.getDatabases();
redesigned SyncSource base class + API The main motivation for this change is that it allows the implementor of a backend to choose the implementations for the different aspects of a datasource (change tracking, item import/export, logging, ...) independently of each other. For example, change tracking via revision strings can now be combined with exchanging data with the Synthesis engine via a single string (the traditional method in SyncEvolution) and with direct access to the Synthesis field list (now possible for the first time). The new backend API is based on the concept of providing implementations for certain functionality via function objects instead of implementing certain virtual methods. The advantage is that implementors can define their own, custom interfaces and mix and match implementations of the different groups of functionality. Logging (see SyncSourceLogging in a later commit) can be done by wrapping some arbitrary other item import/export function objects (decorator design pattern). The class hierarchy is now this: - SyncSourceBase: interface for common utility code, all other classes are derived from it and thus can use that code - SyncSource: base class which implements SyncSourceBase and hooks a datasource into the SyncEvolution core; its "struct Operations" holds the function objects which can be implemented in different ways - TestingSyncSource: combines some of the following classes into an interface that is expected by the client-test program; backends only have to derive from (and implement this) if they want to use the automated testing - TrackingSyncSource: provides the same functionality as before (change tracking via revision strings, item import/export as string) in a single interface; the description of the pure virtual methods are duplicated so that developers can go through this class and find everything they need to know to implement it The following classes contain the code that was previously found in the EvolutionSyncSource base class. Implementors can derive from them and call the init() methods to inherit and activate the functionality: - SyncSourceSession: binds Synthesis session callbacks to virtual methods beginSync(), endSync() - SyncSourceChanges: implements Synthesis item tracking callbacks with set of LUIDs that the user of the class has to fill - SyncSourceDelete: binds Synthesis delete callback to virtual method - SyncSourceRaw: read and write items in the backends format, used for testing and backup/restore - SyncSourceSerialize: exchanges items with Synthesis engine using a string representation of the data; this is how EvolutionSyncSource has traditionally worked, so much of the same virtual methods are now in this class - SyncSourceRevisions: utility class which does change tracking via some kind of "revision" string which changes each time an item is modified; this code was previously in the TrackingSyncSource
2009-08-25 09:27:46 +02:00
BOOST_FOREACH(const SyncSource::Database &database, databases) {
m_out << " " << database.m_name << " (" << database.m_uri << ")";
if (database.m_isDefault) {
m_out << " <default>";
}
m_out << endl;
}
}
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
void Cmdline::dumpConfigs(const string &preamble,
const SyncConfig::ConfigList &servers)
{
m_out << preamble << endl;
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
BOOST_FOREACH(const SyncConfig::ConfigList::value_type &server,servers) {
m_out << " " << server.first << " = " << server.second <<endl;
}
if (!servers.size()) {
m_out << " none" << endl;
}
}
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
void Cmdline::dumpConfigTemplates(const string &preamble,
const SyncConfig::TemplateList &templates,
bool printRank)
{
m_out << preamble << endl;
m_out << " " << "template name" << " = " << "template description";
if (printRank) {
m_out << " " << "matching score in percent (100% = exact match)";
}
m_out << endl;
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
BOOST_FOREACH(const SyncConfig::TemplateList::value_type server,templates) {
m_out << " " << server->m_templateId << " = " << server->m_description;
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
if (printRank){
m_out << " " << server->m_rank *20 << "%";
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
}
m_out << endl;
}
if (!templates.size()) {
m_out << " none" << endl;
}
}
void Cmdline::dumpProperties(const ConfigNode &configuredProps,
const ConfigPropertyRegistry &allProps,
int flags)
{
list<string> perPeer, perContext, global;
BOOST_FOREACH(const ConfigProperty *prop, allProps) {
if (prop->isHidden() ||
((flags & HIDE_PER_PEER) &&
prop->getSharing() == ConfigProperty::NO_SHARING)) {
continue;
}
if (!m_quiet) {
string comment = prop->getComment();
if (!comment.empty()) {
m_out << endl;
dumpComment(m_out, "# ", comment);
}
}
bool isDefault;
prop->getProperty(configuredProps, &isDefault);
if (isDefault) {
m_out << "# ";
}
m_out << prop->getMainName() << " = " << prop->getProperty(configuredProps) << endl;
list<string> *type = NULL;
switch (prop->getSharing()) {
case ConfigProperty::GLOBAL_SHARING:
type = &global;
break;
case ConfigProperty::SOURCE_SET_SHARING:
type = &perContext;
break;
case ConfigProperty::NO_SHARING:
type = &perPeer;
break;
}
if (type) {
type->push_back(prop->getMainName());
}
}
if (!m_quiet && !(flags & HIDE_LEGEND)) {
if (!perPeer.empty() ||
!perContext.empty() ||
!global.empty()) {
m_out << endl;
}
if (!perPeer.empty()) {
m_out << "# per-peer (unshared) properties: " << boost::join(perPeer, ", ") << endl;
}
if (!perContext.empty()) {
m_out << "# shared by peers in same context: " << boost::join(perContext, ", ") << endl;
}
if (!global.empty()) {
m_out << "# global properties: " << boost::join(global, ", ") << endl;
}
}
}
void Cmdline::dumpComment(ostream &stream,
const string &prefix,
const string &comment)
{
list<string> commentLines;
ConfigProperty::splitComment(comment, commentLines);
BOOST_FOREACH(const string &line, commentLines) {
stream << prefix << line << endl;
}
}
void Cmdline::usage(bool full, const string &error, const string &param)
{
ostream &out(error.empty() ? m_out : m_err);
out << synopsis;
if (full) {
out << endl <<
"Options:" << endl <<
options;
}
if (error != "") {
out << endl << "ERROR: " << error << endl;
}
if (param != "") {
out << "INFO: use '" << param << (param[param.size() - 1] == '=' ? "" : " ") <<
"?' to get a list of valid parameters" << endl;
}
}
SyncContext* Cmdline::createSyncClient() {
return new SyncContext(m_server, true);
}
#ifdef ENABLE_UNIT_TESTS
/** simple line-by-line diff */
static string diffStrings(const string &lhs, const string &rhs)
{
ostringstream res;
typedef boost::split_iterator<string::const_iterator> string_split_iterator;
string_split_iterator lit =
boost::make_split_iterator(lhs, boost::first_finder("\n", boost::is_iequal()));
string_split_iterator rit =
boost::make_split_iterator(rhs, boost::first_finder("\n", boost::is_iequal()));
while (lit != string_split_iterator() &&
rit != string_split_iterator()) {
if (*lit != *rit) {
res << "< " << *lit << endl;
res << "> " << *rit << endl;
}
++lit;
++rit;
}
while (lit != string_split_iterator()) {
res << "< " << *lit << endl;
++lit;
}
while (rit != string_split_iterator()) {
res << "> " << *rit << endl;
++rit;
}
return res.str();
}
# define CPPUNIT_ASSERT_EQUAL_DIFF( expected, actual ) \
do { \
string expected_ = (expected); \
string actual_ = (actual); \
if (expected_ != actual_) { \
CPPUNIT_NS::Message cpputMsg_(string("expected:\n") + \
expected_); \
cpputMsg_.addDetail(string("actual:\n") + \
actual_); \
cpputMsg_.addDetail(string("diff:\n") + \
diffStrings(expected_, actual_)); \
CPPUNIT_NS::Asserter::fail( cpputMsg_, \
CPPUNIT_SOURCELINE() ); \
} \
} while ( false )
// returns last line, including trailing line break, empty if input is empty
static string lastLine(const string &buffer)
{
if (buffer.size() < 2) {
return buffer;
}
size_t line = buffer.rfind("\n", buffer.size() - 2);
if (line == buffer.npos) {
return buffer;
}
return buffer.substr(line + 1);
}
// true if <word> =
static bool isPropAssignment(const string &buffer) {
// ignore these comments (occur in type description)
if (boost::starts_with(buffer, "KCalExtended = ") ||
boost::starts_with(buffer, "mkcal = ") ||
boost::starts_with(buffer, "QtContacts = ")) {
return false;
}
size_t start = 0;
while (start < buffer.size() &&
!isspace(buffer[start])) {
start++;
}
if (start + 3 <= buffer.size() &&
buffer.substr(start, 3) == " = ") {
return true;
} else {
return false;
}
}
// remove pure comment lines from buffer,
// also empty lines,
// also defaultPeer (because reference properties do not include global props)
static string filterConfig(const string &buffer)
{
ostringstream res;
typedef boost::split_iterator<string::const_iterator> string_split_iterator;
for (string_split_iterator it =
boost::make_split_iterator(buffer, boost::first_finder("\n", boost::is_iequal()));
it != string_split_iterator();
++it) {
string line = boost::copy_range<string>(*it);
if (!line.empty() &&
line.find("defaultPeer =") == line.npos &&
(!boost::starts_with(line, "# ") ||
isPropAssignment(line.substr(2)))) {
res << line << endl;
}
}
return res.str();
}
static string injectValues(const string &buffer)
{
string res = buffer;
// username/password not set in templates, only in configs created via
// the command line
boost::replace_first(res,
"# username = ",
"username = your SyncML server account name");
boost::replace_first(res,
"# password = ",
"password = your SyncML server password");
return res;
}
// remove lines indented with spaces
static string filterIndented(const string &buffer)
{
ostringstream res;
bool first = true;
typedef boost::split_iterator<string::const_iterator> string_split_iterator;
for (string_split_iterator it =
boost::make_split_iterator(buffer, boost::first_finder("\n", boost::is_iequal()));
it != string_split_iterator();
++it) {
if (!boost::starts_with(*it, " ")) {
if (!first) {
res << endl;
} else {
first = false;
}
res << *it;
}
}
return res.str();
}
// sort lines by file, preserving order inside each line
static void sortConfig(string &config)
{
// file name, line number, property
typedef pair<string, pair<int, string> > line_t;
vector<line_t> lines;
typedef boost::split_iterator<string::iterator> string_split_iterator;
int linenr = 0;
for (string_split_iterator it =
boost::make_split_iterator(config, boost::first_finder("\n", boost::is_iequal()));
it != string_split_iterator();
++it, ++linenr) {
string line(it->begin(), it->end());
if (line.empty()) {
continue;
}
size_t colon = line.find(':');
string prefix = line.substr(0, colon);
lines.push_back(make_pair(prefix, make_pair(linenr, line.substr(colon))));
}
// stable sort because of line number
sort(lines.begin(), lines.end());
size_t len = config.size();
config.resize(0);
config.reserve(len);
BOOST_FOREACH(const line_t &line, lines) {
config += line.first;
config += line.second.second;
config += "\n";
}
}
// convert the internal config dump to .ini style (--print-config)
static string internalToIni(const string &config)
{
ostringstream res;
string section;
typedef boost::split_iterator<string::const_iterator> string_split_iterator;
for (string_split_iterator it =
boost::make_split_iterator(config, boost::first_finder("\n", boost::is_iequal()));
it != string_split_iterator();
++it) {
string line(it->begin(), it->end());
if (line.empty()) {
continue;
}
size_t colon = line.find(':');
string prefix = line.substr(0, colon);
// internal values are not part of the --print-config output
if (boost::contains(prefix, ".internal.ini") ||
boost::contains(line, "= internal value")) {
continue;
}
// --print-config also doesn't duplicate the "type" property
// => remove the shared property
if (boost::contains(line, ":type = ") &&
boost::starts_with(line, "sources/")) {
continue;
}
// sources/<name>/config.ini or
// spds/sources/<name>/config.ini
size_t endslash = prefix.rfind('/');
if (endslash != line.npos && endslash > 1) {
size_t slash = prefix.rfind('/', endslash - 1);
if (slash != line.npos) {
string newsource = prefix.substr(slash + 1, endslash - slash - 1);
if (newsource != section &&
prefix.find("/sources/") != prefix.npos &&
newsource != "syncml") {
res << "[" << newsource << "]" << endl;
section = newsource;
}
}
}
string assignment = line.substr(colon + 1);
// substitude aliases with generic values
boost::replace_first(assignment, "= F", "= 0");
boost::replace_first(assignment, "= T", "= 1");
boost::replace_first(assignment, "= syncml:auth-md5", "= md5");
boost::replace_first(assignment, "= syncml:auth-basix", "= basic");
res << assignment << endl;
}
return res.str();
}
/**
* Testing is based on a text representation of a directory
* hierarchy where each line is of the format
* <file path>:<line in file>
*
* The order of files is alphabetical, of lines in the file as
* in the file. Lines in the file without line break cannot
* be represented.
*
* The root of the hierarchy is not part of the representation
* itself.
*/
class CmdlineTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(CmdlineTest);
CPPUNIT_TEST(testFramework);
CPPUNIT_TEST(testSetupScheduleWorld);
CPPUNIT_TEST(testFutureConfig);
CPPUNIT_TEST(testPeerConfigMigration);
CPPUNIT_TEST(testContextConfigMigration);
CPPUNIT_TEST(testSetupDefault);
CPPUNIT_TEST(testSetupRenamed);
CPPUNIT_TEST(testSetupFunambol);
CPPUNIT_TEST(testSetupSynthesis);
CPPUNIT_TEST(testPrintServers);
CPPUNIT_TEST(testPrintConfig);
CPPUNIT_TEST(testPrintFileTemplates);
CPPUNIT_TEST(testPrintFileTemplatesConfig);
CPPUNIT_TEST(testTemplate);
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
CPPUNIT_TEST(testMatchTemplate);
CPPUNIT_TEST(testAddSource);
CPPUNIT_TEST(testSync);
CPPUNIT_TEST(testConfigure);
CPPUNIT_TEST(testConfigureSources);
CPPUNIT_TEST(testOldConfigure);
CPPUNIT_TEST(testListSources);
CPPUNIT_TEST(testMigrate);
CPPUNIT_TEST_SUITE_END();
public:
CmdlineTest() :
m_testDir("CmdlineTest")
{
}
protected:
/** verify that createFiles/scanFiles themselves work */
void testFramework() {
const string root(m_testDir);
const string content("baz:line\n"
"caz/subdir:booh\n"
"caz/subdir2/sub:# comment\n"
"caz/subdir2/sub:# foo = bar\n"
"caz/subdir2/sub:# empty = \n"
"caz/subdir2/sub:# another comment\n"
"foo:bar1\n"
"foo:\n"
"foo: \n"
"foo:bar2\n");
const string filtered("baz:line\n"
"caz/subdir:booh\n"
"caz/subdir2/sub:# foo = bar\n"
"caz/subdir2/sub:# empty = \n"
"foo:bar1\n"
"foo: \n"
"foo:bar2\n");
createFiles(root, content);
string res = scanFiles(root);
CPPUNIT_ASSERT_EQUAL_DIFF(filtered, res);
}
void removeRandomUUID(string &buffer) {
string uuidstr = "deviceId = syncevolution-";
size_t uuid = buffer.find(uuidstr);
CPPUNIT_ASSERT(uuid != buffer.npos);
size_t end = buffer.find("\n", uuid + uuidstr.size());
CPPUNIT_ASSERT(end != buffer.npos);
buffer.replace(uuid, end - uuid, "deviceId = fixed-devid");
}
/** create new configurations */
void testSetupScheduleWorld() { doSetupScheduleWorld(false); }
void doSetupScheduleWorld(bool shared) {
string root;
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
root = m_testDir;
root += "/syncevolution/default";
string peer;
if (shared) {
peer = root + "/peers/scheduleworld";
} else {
peer = root;
}
{
rm_r(peer);
TestCmdline cmdline("--configure",
"--sync-property", "proxyHost = proxy",
"scheduleworld",
"addressbook",
NULL);
cmdline.doit();
string res = scanFiles(root);
removeRandomUUID(res);
string expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_first(expected,
"# proxyHost = ",
"proxyHost = proxy");
boost::replace_all(expected,
"sync = two-way",
"sync = disabled");
boost::replace_first(expected,
"addressbook/config.ini:sync = disabled",
"addressbook/config.ini:sync = two-way");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
{
rm_r(peer);
TestCmdline cmdline("--configure",
"--sync-property", "deviceID = fixed-devid",
"scheduleworld",
NULL);
cmdline.doit();
string res = scanFiles(root);
string expected = ScheduleWorldConfig();
sortConfig(expected);
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
}
void expectTooOld() {
bool caught = false;
try {
SyncConfig config("scheduleworld");
} catch (const StatusException &ex) {
caught = true;
if (ex.syncMLStatus() != STATUS_RELEASE_TOO_OLD) {
throw;
} else {
CPPUNIT_ASSERT_EQUAL(StringPrintf("SyncEvolution %s is too old to read configuration 'scheduleworld', please upgrade SyncEvolution.", VERSION),
string(ex.what()));
}
}
CPPUNIT_ASSERT(caught);
}
void testFutureConfig() {
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
doSetupScheduleWorld(false);
// bump min/cur version to something not supported, then
// try to read => should fail
IniFileConfigNode root(m_testDir, "/syncevolution/.internal.ini", false);
IniFileConfigNode context(m_testDir + "/syncevolution/default", ".internal.ini", false);
IniFileConfigNode peer(m_testDir + "/syncevolution/default/peers/scheduleworld", ".internal.ini", false);
root.setProperty("rootMinVersion", StringPrintf("%d", CONFIG_ROOT_MIN_VERSION + 1));
root.setProperty("rootCurVersion", StringPrintf("%d", CONFIG_ROOT_CUR_VERSION + 1));
root.flush();
context.setProperty("contextMinVersion", StringPrintf("%d", CONFIG_CONTEXT_MIN_VERSION + 1));
context.setProperty("contextCurVersion", StringPrintf("%d", CONFIG_CONTEXT_CUR_VERSION + 1));
context.flush();
peer.setProperty("peerMinVersion", StringPrintf("%d", CONFIG_PEER_MIN_VERSION + 1));
peer.setProperty("peerCurVersion", StringPrintf("%d", CONFIG_PEER_CUR_VERSION + 1));
peer.flush();
expectTooOld();
root.setProperty("rootMinVersion", StringPrintf("%d", CONFIG_ROOT_MIN_VERSION));
root.flush();
expectTooOld();
context.setProperty("contextMinVersion", StringPrintf("%d", CONFIG_CONTEXT_MIN_VERSION));
context.flush();
expectTooOld();
// okay now
peer.setProperty("peerMinVersion", StringPrintf("%d", CONFIG_PEER_MIN_VERSION));
peer.flush();
SyncConfig config("scheduleworld");
}
void expectMigration(const std::string &config) {
bool caught = false;
try {
SyncConfig c(config);
c.prepareConfigForWrite();
} catch (const StatusException &ex) {
caught = true;
if (ex.syncMLStatus() != STATUS_MIGRATION_NEEDED) {
throw;
} else {
CPPUNIT_ASSERT_EQUAL(StringPrintf("Proceeding would modify config '%s' such that the "
"previous SyncEvolution release will not be able to use it. "
"Stopping now. Please explicitly acknowledge this step by "
"running the following command on the command line: "
"syncevolution --migrate '%s'",
config.c_str(),
config.c_str()),
string(ex.what()));
}
}
CPPUNIT_ASSERT(caught);
}
void testPeerConfigMigration() {
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
doSetupScheduleWorld(false);
// decrease min/cur version to something no longer supported,
// then try to write => should migrate in release mode and fail otherwise
IniFileConfigNode peer(m_testDir + "/syncevolution/default/peers/scheduleworld", ".internal.ini", false);
peer.setProperty("peerMinVersion", StringPrintf("%d", CONFIG_PEER_CUR_VERSION - 1));
peer.setProperty("peerCurVersion", StringPrintf("%d", CONFIG_PEER_CUR_VERSION - 1));
peer.flush();
SyncContext::setStableRelease(false);
expectMigration("scheduleworld");
SyncContext::setStableRelease(true);
{
SyncConfig config("scheduleworld");
config.prepareConfigForWrite();
}
{
TestCmdline cmdline("--print-servers", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Configured servers:\n"
" scheduleworld = CmdlineTest/syncevolution/default/peers/scheduleworld\n"
" scheduleworld.old = CmdlineTest/syncevolution/default/peers/scheduleworld.old\n",
cmdline.m_out.str());
}
// should be okay now
SyncContext::setStableRelease(false);
{
SyncConfig config("scheduleworld");
config.prepareConfigForWrite();
}
// do the same migration with command line
SyncContext::setStableRelease(false);
rm_r(m_testDir + "/syncevolution/default/peers/scheduleworld");
CPPUNIT_ASSERT_EQUAL(0, rename((m_testDir + "/syncevolution/default/peers/scheduleworld.old").c_str(),
(m_testDir + "/syncevolution/default/peers/scheduleworld").c_str()));
{
TestCmdline cmdline("--migrate", "scheduleworld", NULL);
cmdline.doit();
}
{
SyncConfig config("scheduleworld");
config.prepareConfigForWrite();
}
{
TestCmdline cmdline("--print-servers", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Configured servers:\n"
" scheduleworld = CmdlineTest/syncevolution/default/peers/scheduleworld\n"
" scheduleworld.old = CmdlineTest/syncevolution/default/peers/scheduleworld.old\n",
cmdline.m_out.str());
}
}
void testContextConfigMigration() {
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
doSetupScheduleWorld(false);
// decrease min/cur version to something no longer supported,
// then try to write => should migrate in release mode and fail otherwise
IniFileConfigNode context(m_testDir + "/syncevolution/default", ".internal.ini", false);
context.setProperty("contextMinVersion", StringPrintf("%d", CONFIG_CONTEXT_CUR_VERSION - 1));
context.setProperty("contextCurVersion", StringPrintf("%d", CONFIG_CONTEXT_CUR_VERSION - 1));
context.flush();
SyncContext::setStableRelease(false);
expectMigration("@default");
SyncContext::setStableRelease(true);
{
SyncConfig config("@default");
config.prepareConfigForWrite();
}
{
TestCmdline cmdline("--print-servers", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Configured servers:\n"
" scheduleworld = CmdlineTest/syncevolution/default/peers/scheduleworld\n"
" scheduleworld.old@default.old = CmdlineTest/syncevolution/default.old/peers/scheduleworld.old\n",
cmdline.m_out.str());
}
// should be okay now
SyncContext::setStableRelease(false);
{
SyncConfig config("@default");
config.prepareConfigForWrite();
}
// do the same migration with command line
SyncContext::setStableRelease(false);
rm_r(m_testDir + "/syncevolution/default");
CPPUNIT_ASSERT_EQUAL(0, rename((m_testDir + "/syncevolution/default.old/peers/scheduleworld.old").c_str(),
(m_testDir + "/syncevolution/default.old/peers/scheduleworld").c_str()));
CPPUNIT_ASSERT_EQUAL(0, rename((m_testDir + "/syncevolution/default.old").c_str(),
(m_testDir + "/syncevolution/default").c_str()));
{
TestCmdline cmdline("--migrate", "@default", NULL);
cmdline.doit();
}
{
SyncConfig config("@default");
config.prepareConfigForWrite();
}
{
TestCmdline cmdline("--print-servers", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Configured servers:\n"
" scheduleworld = CmdlineTest/syncevolution/default/peers/scheduleworld\n"
" scheduleworld.old@default.old = CmdlineTest/syncevolution/default.old/peers/scheduleworld.old\n",
cmdline.m_out.str());
}
}
void testSetupDefault() {
string root;
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
root = m_testDir;
root += "/syncevolution/default";
rm_r(root);
TestCmdline cmdline("--configure",
"--template", "default",
"--sync-property", "deviceID = fixed-devid",
"some-other-server",
NULL);
cmdline.doit();
string res = scanFiles(root, "some-other-server");
string expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_all(expected, "/scheduleworld/", "/some-other-server/");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
void testSetupRenamed() {
string root;
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
root = m_testDir;
rm_r(root);
root += "/syncevolution/default";
TestCmdline cmdline("--configure",
"--template", "scheduleworld",
"--sync-property", "deviceID = fixed-devid",
"scheduleworld2",
NULL);
cmdline.doit();
string res = scanFiles(root, "scheduleworld2");
string expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld2/");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
void testSetupFunambol() { doSetupFunambol(false); }
void doSetupFunambol(bool shared) {
string root;
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
root = m_testDir;
root += "/syncevolution/default";
string peer;
if (shared) {
peer = root + "/peers/funambol";
} else {
peer = root;
}
rm_r(peer);
const char * const argv_fixed[] = {
"--configure",
"--sync-property", "deviceID = fixed-devid",
// templates are case-insensitive
"FunamBOL",
NULL
}, * const argv_shared[] = {
"--configure",
"FunamBOL",
NULL
};
TestCmdline cmdline(shared ? argv_shared : argv_fixed);
cmdline.doit();
string res = scanFiles(root, "funambol");
string expected = FunambolConfig();
sortConfig(expected);
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
void testSetupSynthesis() { doSetupSynthesis(false); }
void doSetupSynthesis(bool shared) {
string root;
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
root = m_testDir;
root += "/syncevolution/default";
string peer;
if (shared) {
peer = root + "/peers/synthesis";
} else {
peer = root;
}
rm_r(peer);
const char * const argv_fixed[] = {
"--configure",
"--sync-property", "deviceID = fixed-devid",
"synthesis",
NULL
}, * const argv_shared[] = {
"--configure",
"synthesis",
NULL
};
TestCmdline cmdline(shared ? argv_shared : argv_fixed);
cmdline.doit();
string res = scanFiles(root, "synthesis");
string expected = SynthesisConfig();
sortConfig(expected);
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
void testTemplate() {
TestCmdline failure("--template", NULL);
CPPUNIT_ASSERT(!failure.m_cmdline->parse());
CPPUNIT_ASSERT_EQUAL_DIFF("", failure.m_out.str());
CPPUNIT_ASSERT_EQUAL(string("ERROR: missing parameter for '--template'\n"), lastLine(failure.m_err.str()));
TestCmdline help("--template", "? ", NULL);
help.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
" template name = template description\n"
" Funambol = http://my.funambol.com\n"
" Google = http://m.google.com/sync\n"
" Goosync = http://www.goosync.com/\n"
" Memotoo = http://www.memotoo.com\n"
" Mobical = http://www.mobical.net\n"
" Oracle = http://www.oracle.com/technology/products/beehive/index.html\n"
2010-02-09 04:03:20 +01:00
" Ovi = http://www.ovi.com\n"
" ScheduleWorld = http://www.scheduleworld.com\n"
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
" SyncEvolution = http://www.syncevolution.org\n"
" Synthesis = http://www.synthesis.ch\n",
help.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help.m_err.str());
}
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
void testMatchTemplate() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "testcases/templates");
ScopedEnvChange xdg("XDG_CONFIG_HOME", "/dev/null");
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
TestCmdline help1("--template", "?nokia 7210c", NULL);
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
help1.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
" template name = template description matching score in percent (100% = exact match)\n"
" Nokia 7210c = Template for Nokia S40 series Phone 100%\n"
" SyncEvolution Client = SyncEvolution server side template 40%\n",
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
help1.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help1.m_err.str());
TestCmdline help2("--template", "?nokia", NULL);
help2.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
" template name = template description matching score in percent (100% = exact match)\n"
" Nokia 7210c = Template for Nokia S40 series Phone 100%\n"
" SyncEvolution Client = SyncEvolution server side template 40%\n",
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
help2.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help2.m_err.str());
TestCmdline help3("--template", "?7210c", NULL);
help3.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
" template name = template description matching score in percent (100% = exact match)\n"
" Nokia 7210c = Template for Nokia S40 series Phone 60%\n"
" SyncEvolution Client = SyncEvolution server side template 20%\n",
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
help3.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help3.m_err.str());
TestCmdline help4("--template", "?syncevolution client", NULL);
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
help4.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Available configuration templates:\n"
" template name = template description matching score in percent (100% = exact match)\n"
" SyncEvolution Client = SyncEvolution server side template 100%\n"
" Nokia 7210c = Template for Nokia S40 series Phone 40%\n",
Configuration templates matching: match templates based on metadata Introduced TemplateConfig to abstracting the template configuration structure, the template metadata used for matching is also parsed here. The fields introduced in the metadata are: PeerIsClient: identify whether this is a server side configuration or a client side configuration. Fingerprint: the matching string for this template, it is a comma separated string with each string modeled as: "Manufacture_Model". The first substring is also used as the name to identify this template so that user can select the template by this name. eg: Nokia 7210c: Nokia_7210c SyncEvolution server: SyncEvolutionServer, SyncEvolution ScheduleWorld: ScheduleWorld,default SyncEvolution client: SyncEvolutionClient, SyncEvolution Description: this is a just a descriptive string not used for matching. GetServerTemplates is changed to add another "devices" parameter to identify it is asking for templates for a list of "devices". Each device is a tuple <matchstring (devicename), matchMode (server/client/all)>. TemplateList as the return type, which is a list of class TemplateDescription so that we can also return enough information for corresponding templates. This list is sorted by the 3-tuple <finger, rank, name>. Add MatchServerTemplates method which will iterating all templates inside the folder and match against the input parameter and finally return a sorted list of matched templates. The atcually fuzzy match algorithm is based on a LCS (added in the following commit). Cmdline interface is changed accordingly: --template ? is changed to --template ?[string], so that user use the former case to match all templates for a tradiontial SyncML client and the latter case to match templates related to an input string. SyncConfig API is also renamed (Server -> Peer) because both server/client configuration/template are handled. The original configuration template (Funambol and ScheduleWorld) has been moved to the new template structure (under servers), they also have a .template.ini file added so that they can be matched and picked up. All templates for supported servers still have built-in template support in the code as before. Templates for SyncEvolution based server is also added. Server side templates are added (Nokia default, Nokia_7210c and SyncEvolutionServer). Add unit test for the new template match use case.
2010-01-19 08:01:05 +01:00
help4.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help4.m_err.str());
}
void testPrintServers() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
doSetupScheduleWorld(false);
doSetupSynthesis(true);
doSetupFunambol(true);
TestCmdline cmdline("--print-servers", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("Configured servers:\n"
" funambol = CmdlineTest/syncevolution/default/peers/funambol\n"
" scheduleworld = CmdlineTest/syncevolution/default/peers/scheduleworld\n"
" synthesis = CmdlineTest/syncevolution/default/peers/synthesis\n",
cmdline.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
}
void testPrintConfig() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
testSetupFunambol();
{
TestCmdline failure("--print-config", NULL);
CPPUNIT_ASSERT(failure.m_cmdline->parse());
CPPUNIT_ASSERT(!failure.m_cmdline->run());
CPPUNIT_ASSERT_EQUAL_DIFF("", failure.m_out.str());
CPPUNIT_ASSERT_EQUAL(string("ERROR: --print-config requires either a --template or a server name.\n"),
lastLine(failure.m_err.str()));
}
{
TestCmdline failure("--print-config", "foo", NULL);
CPPUNIT_ASSERT(failure.m_cmdline->parse());
CPPUNIT_ASSERT(!failure.m_cmdline->run());
CPPUNIT_ASSERT_EQUAL_DIFF("", failure.m_out.str());
CPPUNIT_ASSERT_EQUAL(string("ERROR: server 'foo' has not been configured yet.\n"),
lastLine(failure.m_err.str()));
}
{
TestCmdline failure("--print-config", "--template", "foo", NULL);
CPPUNIT_ASSERT(failure.m_cmdline->parse());
CPPUNIT_ASSERT(!failure.m_cmdline->run());
CPPUNIT_ASSERT_EQUAL_DIFF("", failure.m_out.str());
CPPUNIT_ASSERT_EQUAL(string("ERROR: no configuration template for 'foo' available.\n"),
lastLine(failure.m_err.str()));
}
{
TestCmdline cmdline("--print-config", "--template", "scheduleworld", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = cmdline.m_out.str();
// deviceId must be the one from Funambol
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
string filtered = injectValues(filterConfig(actual));
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
filtered);
// there should have been comments
CPPUNIT_ASSERT(actual.size() > filtered.size());
}
{
TestCmdline cmdline("--print-config", "--template", "scheduleworld@nosuchcontext", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = cmdline.m_out.str();
// deviceId must *not* be the one from Funambol because of the new context
CPPUNIT_ASSERT(!boost::contains(actual, "deviceId = fixed-devid"));
}
{
TestCmdline cmdline("--print-config", "--template", "Default", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = injectValues(filterConfig(cmdline.m_out.str()));
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
actual);
}
{
TestCmdline cmdline("--print-config", "funambol", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(FunambolConfig())),
injectValues(filterConfig(cmdline.m_out.str())));
}
{
// override context and template properties
TestCmdline cmdline("--print-config", "--template", "scheduleworld",
"--sync-property", "syncURL=foo",
"--source-property", "database=Personal",
"--source-property", "sync=disabled",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
boost::replace_first(expected,
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = foo");
boost::replace_all(expected,
"# database = ",
"database = Personal");
boost::replace_all(expected,
"sync = two-way",
"sync = disabled");
string actual = injectValues(filterConfig(cmdline.m_out.str()));
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
actual);
}
{
// override context and template properties, using legacy property name
TestCmdline cmdline("--print-config", "--template", "scheduleworld",
"--sync-property", "syncURL=foo",
"--source-property", "evolutionsource=Personal",
"--source-property", "sync=disabled",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
boost::replace_first(expected,
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = foo");
boost::replace_all(expected,
"# database = ",
"database = Personal");
boost::replace_all(expected,
"sync = two-way",
"sync = disabled");
string actual = injectValues(filterConfig(cmdline.m_out.str()));
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
actual);
}
{
TestCmdline cmdline("--print-config", "--quiet",
"--template", "scheduleworld",
"funambol",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = cmdline.m_out.str();
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
CPPUNIT_ASSERT_EQUAL_DIFF(internalToIni(ScheduleWorldConfig()),
injectValues(filterConfig(actual)));
}
{
// change shared source properties, then check template again
TestCmdline cmdline("--configure",
"--source-property", "database=Personal",
"funambol",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
}
{
TestCmdline cmdline("--print-config", "--quiet",
"--template", "scheduleworld",
"funambol",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
// from modified Funambol config
boost::replace_all(expected,
"# database = ",
"database = Personal");
string actual = injectValues(filterConfig(cmdline.m_out.str()));
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
actual);
}
{
// print config => must not use settings from default context
TestCmdline cmdline("--print-config", "--template", "scheduleworld@nosuchcontext", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
// source settings *not* from modified Funambol config
string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
string actual = injectValues(filterConfig(cmdline.m_out.str()));
CPPUNIT_ASSERT(!boost::contains(actual, "deviceId = fixed-devid"));
removeRandomUUID(actual);
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
actual);
}
{
// create config => again, must not use settings from default context
TestCmdline cmdline("--configure", "--template", "scheduleworld", "other@other", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
}
{
TestCmdline cmdline("--print-config", "other@other", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
// source settings *not* from modified Funambol config
string expected = filterConfig(internalToIni(ScheduleWorldConfig()));
string actual = injectValues(filterConfig(cmdline.m_out.str()));
CPPUNIT_ASSERT(!boost::contains(actual, "deviceId = fixed-devid"));
removeRandomUUID(actual);
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
actual);
}
}
void testPrintFileTemplates() {
rm_r(m_testDir);
// use local copy of templates in build dir (no need to install)
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "./templates");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
doPrintFileTemplates();
}
void testPrintFileTemplatesConfig() {
rm_r(m_testDir);
mkdir_p(m_testDir);
symlink("../templates", (m_testDir + "/syncevolution-templates").c_str());
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
doPrintFileTemplates();
}
void doPrintFileTemplates() {
testSetupFunambol();
{
TestCmdline cmdline("--print-config", "--template", "scheduleworld", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
string actual = cmdline.m_out.str();
// deviceId must be the one from Funambol
CPPUNIT_ASSERT(boost::contains(actual, "deviceId = fixed-devid"));
string filtered = injectValues(filterConfig(actual));
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(ScheduleWorldConfig())),
filtered);
// there should have been comments
CPPUNIT_ASSERT(actual.size() > filtered.size());
}
{
TestCmdline cmdline("--print-config", "funambol", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF(filterConfig(internalToIni(FunambolConfig())),
injectValues(filterConfig(cmdline.m_out.str())));
}
}
void testAddSource() {
string root;
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
testSetupScheduleWorld();
root = m_testDir;
root += "/syncevolution/default";
{
TestCmdline cmdline("--configure",
"--source-property", "uri = dummy",
"scheduleworld",
"xyz",
NULL);
cmdline.doit();
string res = scanFiles(root);
string expected = ScheduleWorldConfig();
expected += "\n"
"peers/scheduleworld/sources/xyz/.internal.ini:# adminData = \n"
"peers/scheduleworld/sources/xyz/.internal.ini:# synthesisID = 0\n"
"peers/scheduleworld/sources/xyz/config.ini:# sync = disabled\n"
"peers/scheduleworld/sources/xyz/config.ini:uri = dummy\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"peers/scheduleworld/sources/xyz/config.ini:# syncFormat = \n"
"peers/scheduleworld/sources/xyz/config.ini:# forceSyncFormat = 0\n"
"sources/xyz/config.ini:# backend = select backend\n"
"sources/xyz/config.ini:# database = \n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/xyz/config.ini:# databaseFormat = \n"
"sources/xyz/config.ini:# databaseUser = \n"
"sources/xyz/config.ini:# databasePassword = ";
sortConfig(expected);
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
}
}
void testSync() {
TestCmdline failure("--sync", NULL);
CPPUNIT_ASSERT(!failure.m_cmdline->parse());
CPPUNIT_ASSERT_EQUAL_DIFF("", failure.m_out.str());
CPPUNIT_ASSERT_EQUAL(string("ERROR: missing parameter for '--sync'\n"), lastLine(failure.m_err.str()));
TestCmdline failure2("--sync", "foo", NULL);
CPPUNIT_ASSERT(!failure2.m_cmdline->parse());
CPPUNIT_ASSERT_EQUAL_DIFF("", failure2.m_out.str());
CPPUNIT_ASSERT_EQUAL(string("ERROR: '--sync foo': not one of the valid values (two-way, slow, refresh-from-client = refresh-client, refresh-from-server = refresh-server = refresh, one-way-from-client = one-way-client, one-way-from-server = one-way-server = one-way, disabled = none)\n"), lastLine(failure2.m_err.str()));
TestCmdline help("--sync", " ?", NULL);
help.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("--sync\n"
" Requests a certain synchronization mode when initiating a sync:\n"
" two-way = only send/receive changes since last sync\n"
" slow = exchange all items\n"
" refresh-from-client = discard all remote items and replace with\n"
" the items on the client\n"
" refresh-from-server = discard all local items and replace with\n"
" the items on the server\n"
" one-way-from-client = transmit changes from client\n"
" one-way-from-server = transmit changes from server\n"
" disabled (or none) = synchronization disabled\n"
" When accepting a sync session in a SyncML server (HTTP server), only\n"
" sources with sync != disabled are made available to the client,\n"
" which chooses the final sync mode based on its own configuration.\n"
" When accepting a sync session in a SyncML client (local sync with\n"
" the server contacting SyncEvolution on a device), the sync mode\n"
" specified in the client is typically overriden by the server.\n",
help.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", help.m_err.str());
TestCmdline filter("--sync", "refresh-from-server", NULL);
CPPUNIT_ASSERT(filter.m_cmdline->parse());
CPPUNIT_ASSERT(!filter.m_cmdline->run());
CPPUNIT_ASSERT_EQUAL_DIFF("", filter.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("sync = refresh-from-server",
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
string(filter.m_cmdline->m_props[""].m_sourceProps[""]));
CPPUNIT_ASSERT_EQUAL_DIFF("", string(filter.m_cmdline->m_props[""].m_syncProps));
TestCmdline filter2("--source-property", "sync=refresh", NULL);
CPPUNIT_ASSERT(filter2.m_cmdline->parse());
CPPUNIT_ASSERT(!filter2.m_cmdline->run());
CPPUNIT_ASSERT_EQUAL_DIFF("", filter2.m_out.str());
CPPUNIT_ASSERT_EQUAL_DIFF("sync = refresh",
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
string(filter2.m_cmdline->m_props[""].m_sourceProps[""]));
CPPUNIT_ASSERT_EQUAL_DIFF("",
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
string(filter2.m_cmdline->m_props[""].m_syncProps));
}
void testConfigure() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
testSetupScheduleWorld();
string expected = doConfigure(ScheduleWorldConfig(), "sources/addressbook/config.ini:");
{
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
// updating "type" for peer is mapped to updating "backend",
// "databaseFormat", "syncFormat", "forceSyncFormat"
TestCmdline cmdline("--configure",
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
"--source-property", "addressbook/type=file:text/vcard:3.0",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_first(expected,
"backend = addressbook",
"backend = file");
boost::replace_first(expected,
"# databaseFormat = ",
"databaseFormat = text/vcard");
boost::replace_first(expected,
"# forceSyncFormat = 0",
"forceSyncFormat = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
filterConfig(printConfig("scheduleworld")));
string shared = filterConfig(printConfig("@default"));
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
CPPUNIT_ASSERT(shared.find("backend = file") != shared.npos);
CPPUNIT_ASSERT(shared.find("databaseFormat = text/vcard") != shared.npos);
}
{
// updating type for context must not affect peer
TestCmdline cmdline("--configure",
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"--source-property", "type=file:text/x-vcard:2.1",
"@default", "addressbook",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_first(expected,
"databaseFormat = text/vcard",
"databaseFormat = text/x-vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
filterConfig(printConfig("scheduleworld")));
string shared = filterConfig(printConfig("@default"));
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
CPPUNIT_ASSERT(shared.find("backend = file") != shared.npos);
CPPUNIT_ASSERT(shared.find("databaseFormat = text/x-vcard") != shared.npos);
}
string syncProperties("syncURL:\n"
"\n"
"username:\n"
"\n"
"password:\n"
"\n"
"logdir:\n"
"\n"
"loglevel:\n"
"\n"
"printChanges:\n"
"\n"
"dumpData:\n"
"\n"
"maxlogdirs:\n"
"\n"
"autoSync:\n"
"\n"
"autoSyncInterval:\n"
"\n"
"autoSyncDelay:\n"
"\n"
"preventSlowSync:\n"
"\n"
"useProxy:\n"
"\n"
"proxyHost:\n"
"\n"
"proxyUsername:\n"
"\n"
"proxyPassword:\n"
"\n"
"clientAuthType:\n"
"\n"
"RetryDuration:\n"
"\n"
"RetryInterval:\n"
"\n"
"remoteIdentifier:\n"
"\n"
"PeerIsClient:\n"
"\n"
"SyncMLVersion:\n"
"\n"
"PeerName:\n"
"\n"
"deviceId:\n"
"\n"
"remoteDeviceId:\n"
"\n"
"enableWBXML:\n"
"\n"
"maxMsgSize:\n"
"maxObjSize:\n"
"\n"
"enableCompression:\n"
"\n"
"SSLServerCertificates:\n"
"\n"
"SSLVerifyServer:\n"
"\n"
"SSLVerifyHost:\n"
"\n"
"WebURL:\n"
"\n"
"IconURI:\n"
"\n"
"ConsumerReady:\n"
"\n"
"defaultPeer:\n");
string sourceProperties("sync:\n"
"\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"uri:\n"
"\n"
"backend:\n"
"\n"
"syncFormat:\n"
"\n"
"forceSyncFormat:\n"
"\n"
"database:\n"
"\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"databaseFormat:\n"
"\n"
"databaseUser:\n"
"databasePassword:\n");
{
TestCmdline cmdline("--sync-property", "?",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF(syncProperties,
filterIndented(cmdline.m_out.str()));
}
{
TestCmdline cmdline("--source-property", "?",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF(sourceProperties,
filterIndented(cmdline.m_out.str()));
}
{
TestCmdline cmdline("--source-property", "?",
"--sync-property", "?",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF(sourceProperties + syncProperties,
filterIndented(cmdline.m_out.str()));
}
{
TestCmdline cmdline("--sync-property", "?",
"--source-property", "?",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF(syncProperties + sourceProperties,
filterIndented(cmdline.m_out.str()));
}
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
{
TestCmdline cmdline("--source-property", "sync=?",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("'--source-property sync=?'\n",
filterIndented(cmdline.m_out.str()));
}
}
void testConfigureSources() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
// create from scratch with only addressbook configured
{
TestCmdline cmdline("--configure",
"--source-property", "database = file://tmp/test",
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"--source-property", "type = file:text/x-vcard",
"@foobar",
"addressbook",
NULL);
cmdline.doit();
}
string root = m_testDir;
root += "/syncevolution/foobar";
string res = scanFiles(root);
removeRandomUUID(res);
string expected =
StringPrintf(".internal.ini:contextMinVersion = %d\n"
".internal.ini:contextCurVersion = %d\n"
"config.ini:# logdir = \n"
"config.ini:# maxlogdirs = 10\n"
"config.ini:deviceId = fixed-devid\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/addressbook/config.ini:backend = file\n"
"sources/addressbook/config.ini:database = file://tmp/test\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/addressbook/config.ini:databaseFormat = text/x-vcard\n"
"sources/addressbook/config.ini:# databaseUser = \n"
"sources/addressbook/config.ini:# databasePassword = \n",
CONFIG_CONTEXT_MIN_VERSION,
CONFIG_CONTEXT_CUR_VERSION);
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
// add calendar
{
TestCmdline cmdline("--configure",
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
"--source-property", "database@foobar = file://tmp/test2",
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"--source-property", "backend = calendar",
"@foobar",
"calendar",
NULL);
cmdline.doit();
}
res = scanFiles(root);
removeRandomUUID(res);
expected +=
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/calendar/config.ini:backend = calendar\n"
"sources/calendar/config.ini:database = file://tmp/test2\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/calendar/config.ini:# databaseFormat = \n"
"sources/calendar/config.ini:# databaseUser = \n"
"sources/calendar/config.ini:# databasePassword = \n";
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
// add ScheduleWorld peer: must reuse existing backend settings
{
TestCmdline cmdline("--configure",
"scheduleworld@foobar",
NULL);
cmdline.doit();
}
res = scanFiles(root);
removeRandomUUID(res);
expected = ScheduleWorldConfig();
boost::replace_all(expected,
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"addressbook/config.ini:backend = addressbook",
"addressbook/config.ini:backend = file");
boost::replace_all(expected,
"addressbook/config.ini:# database = ",
"addressbook/config.ini:database = file://tmp/test");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_all(expected,
"addressbook/config.ini:# databaseFormat = ",
"addressbook/config.ini:databaseFormat = text/x-vcard");
boost::replace_all(expected,
"calendar/config.ini:# database = ",
"calendar/config.ini:database = file://tmp/test2");
sortConfig(expected);
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// disable all sources except for addressbook
{
TestCmdline cmdline("--configure",
"--source-property", "addressbook/sync=two-way",
"--source-property", "sync=none",
"scheduleworld@foobar",
NULL);
cmdline.doit();
}
res = scanFiles(root);
removeRandomUUID(res);
boost::replace_all(expected, "sync = two-way", "sync = disabled");
boost::replace_first(expected, "sync = disabled", "sync = two-way");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, res);
// override type in template while creating from scratch
{
TestCmdline cmdline("--configure",
"--template", "SyncEvolution",
"--source-property", "addressbook/type=file:text/vcard:3.0",
"--source-property", "calendar/type=file:text/calendar:2.0",
"syncevo@syncevo",
NULL);
cmdline.doit();
}
string syncevoroot = m_testDir + "/syncevolution/syncevo";
res = scanFiles(syncevoroot + "/sources/addressbook");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
CPPUNIT_ASSERT(res.find("backend = file\n") != res.npos);
CPPUNIT_ASSERT(res.find("databaseFormat = text/vcard\n") != res.npos);
res = scanFiles(syncevoroot + "/sources/calendar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
CPPUNIT_ASSERT(res.find("backend = file\n") != res.npos);
CPPUNIT_ASSERT(res.find("databaseFormat = text/calendar\n") != res.npos);
}
void testOldConfigure() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
string oldConfig = OldScheduleWorldConfig();
InitList<string> props = InitList<string>("serverNonce") +
"clientNonce" +
"devInfoHash" +
"HashCode" +
"ConfigDate" +
"deviceData" +
"adminData" +
"synthesisID" +
"rootMinVersion" +
"rootCurVersion" +
"contextMinVersion" +
"contextCurVersion" +
"peerMinVersion" +
"peerCurVersion" +
"lastNonce" +
"last";
BOOST_FOREACH(string &prop, props) {
boost::replace_all(oldConfig,
prop + " = ",
prop + " = internal value");
}
rm_r(m_testDir);
createFiles(m_testDir + "/.sync4j/evolution/scheduleworld", oldConfig);
// Cannot read/and write old format anymore.
SyncContext::setStableRelease(false);
expectMigration("scheduleworld");
// Migrate explicitly.
{
TestCmdline cmdline("--migrate", "scheduleworld", NULL);
cmdline.doit();
}
// now test with new format
string expected = ScheduleWorldConfig();
boost::replace_first(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
// migrating "type" sets forceSyncFormat (always)
// and databaseFormat (if format was part of type, as for addressbook)
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
doConfigure(expected, "sources/addressbook/config.ini:");
}
string doConfigure(const string &SWConfig, const string &addressbookPrefix) {
string expected;
{
TestCmdline cmdline("--configure",
"--source-property", "sync = disabled",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
expected = filterConfig(internalToIni(SWConfig));
boost::replace_all(expected,
"sync = two-way",
"sync = disabled");
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
filterConfig(printConfig("scheduleworld")));
}
{
TestCmdline cmdline("--configure",
"--source-property", "sync = one-way-from-server",
"scheduleworld",
"addressbook",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
expected = SWConfig;
boost::replace_all(expected,
"sync = two-way",
"sync = disabled");
boost::replace_first(expected,
addressbookPrefix + "sync = disabled",
addressbookPrefix + "sync = one-way-from-server");
expected = filterConfig(internalToIni(expected));
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
filterConfig(printConfig("scheduleworld")));
}
{
TestCmdline cmdline("--configure",
"--sync", "two-way",
"-z", "database=source",
command line: specify properties per source and config The new format of the property name in --sync-property is: <name>[@<context>|@<peer>@<context>] --source-property also allows a source name: [<source>/]<name>[@<context>|@<peer>@<context>] This allows to set source properties differently for different sources in the same command line invocation. The @<context> or @<peer>@<context> will be used to set properties differently for main and target context in a local sync (not used yet). The advantage of this grammar is that a string can be split purely based on the syntax in PropertySpecifier::StringToPropSpec(). The patch itself is based on the idea of first collecting all of these config property filters in a new case-insensitive hash structure, FullProps in ConfigFilter.cpp/h, as part of parsing command line parameters. Then once specific filters for sync or sources are needed, they are generated from FullProps by collecting all that apply, starting with the ones with lowest priority and overwriting them with more important (= more specific) ones. This also covers additional filters, like the shared properties of the target context when printing a template. Currently FullProps may contain arbitrary source and config names. Typos are not detected, which is both hard to implement (which names and configs are valid in the current invocation?) and also forces users to be very specific (can't apply one set of filters to different configs) - this is the same conflict of interest as in "configure", which allows unknown --enable/disable parameters because they might be relevant in a sub-configure script. SyncConfig itself still only stores the filters which apply to it, not the full set of overrides that the Cmdline has in its m_props. The advantage is that the API remains the same (no change needed or done in the syncevo-dbus-server). The disadvantage is that in a local sync, no information is available about the properties applying to the target context - probably needs to change.
2011-01-25 11:11:53 +01:00
// note priority of suffix: most specific wins
"--sync-property", "maxlogdirs@scheduleworld@default=20",
"--sync-property", "maxlogdirs@default=10",
"--sync-property", "maxlogdirs=5",
"-y", "LOGDIR@default=logdir",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
boost::replace_all(expected,
"sync = one-way-from-server",
"sync = two-way");
boost::replace_all(expected,
"sync = disabled",
"sync = two-way");
boost::replace_all(expected,
"# database = ",
"database = source");
boost::replace_all(expected,
"database = xyz",
"database = source");
boost::replace_all(expected,
"# maxlogdirs = 10",
"maxlogdirs = 20");
boost::replace_all(expected,
"# logdir = ",
"logdir = logdir");
CPPUNIT_ASSERT_EQUAL_DIFF(expected,
filterConfig(printConfig("scheduleworld")));
}
return expected;
}
void testListSources() {
// pick the varargs constructor; NULL alone is ambiguous
TestCmdline cmdline(NULL, NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
// exact output varies, do not test
}
void testMigrate() {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
rm_r(m_testDir);
string oldRoot = m_testDir + "/.sync4j/evolution/scheduleworld";
string newRoot = m_testDir + "/syncevolution/default";
string oldConfig = OldScheduleWorldConfig();
{
// migrate old config
createFiles(oldRoot, oldConfig);
string createdConfig = scanFiles(oldRoot);
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
string migratedConfig = scanFiles(newRoot);
string expected = ScheduleWorldConfig();
sortConfig(expected);
// migrating SyncEvolution < 1.2 configs sets
// ConsumerReady, to keep config visible in the updated
// sync-ui
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
// migrating "type" sets forceSyncFormat (always)
// and databaseFormat (if format was part of type, as for addressbook)
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(oldRoot + ".old");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
{
// rewrite existing config with obsolete properties
// => these properties should get removed
//
// There is one limitation: shared nodes are not rewritten.
// This is acceptable.
createFiles(newRoot + "/peers/scheduleworld",
"config.ini:# obsolete comment\n"
"config.ini:obsoleteprop = foo\n",
true);
string createdConfig = scanFiles(newRoot, "scheduleworld");
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
string migratedConfig = scanFiles(newRoot, "scheduleworld");
string expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(newRoot, "scheduleworld.old");
boost::replace_all(createdConfig, "/scheduleworld/", "/scheduleworld.old/");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
{
// migrate old config with changes and .synthesis directory, a second time
createFiles(oldRoot, oldConfig);
createFiles(oldRoot,
".synthesis/dummy-file.bfi:dummy = foobar\n"
"spds/sources/addressbook/changes/config.txt:foo = bar\n"
"spds/sources/addressbook/changes/config.txt:foo2 = bar2\n",
true);
string createdConfig = scanFiles(oldRoot);
rm_r(newRoot);
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
string migratedConfig = scanFiles(newRoot);
string expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
boost::replace_first(expected,
"peers/scheduleworld/sources/addressbook/config.ini",
"peers/scheduleworld/sources/addressbook/.other.ini:foo = bar\n"
"peers/scheduleworld/sources/addressbook/.other.ini:foo2 = bar2\n"
"peers/scheduleworld/sources/addressbook/config.ini");
boost::replace_first(expected,
"peers/scheduleworld/config.ini",
"peers/scheduleworld/.synthesis/dummy-file.bfi:dummy = foobar\n"
"peers/scheduleworld/config.ini");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(oldRoot + ".old.1");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
}
{
string otherRoot = m_testDir + "/syncevolution/other";
rm_r(otherRoot);
// migrate old config into non-default context
createFiles(oldRoot, oldConfig);
string createdConfig = scanFiles(oldRoot);
{
TestCmdline cmdline("--migrate",
"scheduleworld@other",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
string migratedConfig = scanFiles(otherRoot);
string expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
string renamedConfig = scanFiles(oldRoot + ".old");
CPPUNIT_ASSERT_EQUAL_DIFF(createdConfig, renamedConfig);
// migrate the migrated config again inside the "other" context,
// with no "default" context which might interfere with the tests
//
// ConsumerReady was set as part of previous migration,
// must be removed during migration to hide the migrated
// config from average users.
rm_r(newRoot);
{
TestCmdline cmdline("--migrate",
"scheduleworld@other",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
migratedConfig = scanFiles(otherRoot, "scheduleworld");
expected = ScheduleWorldConfig();
sortConfig(expected);
boost::replace_all(expected, "# ConsumerReady = 0", "ConsumerReady = 1");
boost::replace_first(expected, "# database = ", "database = xyz");
boost::replace_first(expected, "# databaseUser = ", "databaseUser = foo");
boost::replace_first(expected, "# databasePassword = ", "databasePassword = bar");
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
boost::replace_all(expected, "# forceSyncFormat = 0", "forceSyncFormat = 0");
boost::replace_first(expected, "# databaseFormat = ", "databaseFormat = text/vcard");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
renamedConfig = scanFiles(otherRoot, "scheduleworld.old");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old/");
boost::replace_all(expected, "ConsumerReady = 1", "ConsumerReady = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
// migrate once more, this time without the explicit context in
// the config name => must not change the context, need second .old dir
{
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
migratedConfig = scanFiles(otherRoot, "scheduleworld");
boost::replace_all(expected, "/scheduleworld.old/", "/scheduleworld/");
boost::replace_all(expected, "ConsumerReady = 0", "ConsumerReady = 1");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.1");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.1/");
boost::replace_all(expected, "ConsumerReady = 1", "ConsumerReady = 0");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
// remove ConsumerReady: must be remain unset when migrating
// hidden SyncEvolution >= 1.2 configs
{
TestCmdline cmdline("--configure",
"--sync-property", "ConsumerReady=0",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
// migrate once more => keep ConsumerReady unset
{
TestCmdline cmdline("--migrate",
"scheduleworld",
NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_out.str());
}
migratedConfig = scanFiles(otherRoot, "scheduleworld");
boost::replace_all(expected, "/scheduleworld.old.1/", "/scheduleworld/");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, migratedConfig);
renamedConfig = scanFiles(otherRoot, "scheduleworld.old.2");
boost::replace_all(expected, "/scheduleworld/", "/scheduleworld.old.2/");
CPPUNIT_ASSERT_EQUAL_DIFF(expected, renamedConfig);
}
}
const string m_testDir;
private:
/**
* vararg constructor with NULL termination,
* out and error stream into stringstream members
*/
class TestCmdline {
void init() {
m_argv.reset(new const char *[m_argvstr.size() + 1]);
m_argv[0] = "client-test";
for (size_t index = 0;
index < m_argvstr.size();
++index) {
m_argv[index + 1] = m_argvstr[index].c_str();
}
m_cmdline.set(new Cmdline(m_argvstr.size() + 1, m_argv.get(), m_out, m_err), "cmdline");
}
public:
TestCmdline(const char *arg, ...) {
va_list argList;
va_start (argList, arg);
for (const char *curr = arg;
curr;
curr = va_arg(argList, const char *)) {
m_argvstr.push_back(curr);
}
va_end(argList);
init();
}
TestCmdline(const char * const argv[]) {
for (int i = 0; argv[i]; i++) {
m_argvstr.push_back(argv[i]);
}
init();
}
void doit() {
bool success;
success = m_cmdline->parse() &&
m_cmdline->run();
if (m_err.str().size()) {
m_out << endl << m_err.str();
}
CPPUNIT_ASSERT_MESSAGE(m_out.str(), success);
}
ostringstream m_out, m_err;
cxxptr<Cmdline> m_cmdline;
private:
vector<string> m_argvstr;
boost::scoped_array<const char *> m_argv;
};
string ScheduleWorldConfig(int contextMinVersion = CONFIG_CONTEXT_MIN_VERSION,
int contextCurVersion = CONFIG_CONTEXT_CUR_VERSION,
int peerMinVersion = CONFIG_PEER_MIN_VERSION,
int peerCurVersion = CONFIG_PEER_CUR_VERSION) {
// properties sorted by the order in which they are defined
// in the sync and sync source property registry
string config =
StringPrintf("peers/scheduleworld/.internal.ini:peerMinVersion = %d\n"
"peers/scheduleworld/.internal.ini:peerCurVersion = %d\n"
"peers/scheduleworld/.internal.ini:# HashCode = 0\n"
"peers/scheduleworld/.internal.ini:# ConfigDate = \n"
"peers/scheduleworld/.internal.ini:# lastNonce = \n"
"peers/scheduleworld/.internal.ini:# deviceData = \n"
"peers/scheduleworld/config.ini:syncURL = http://sync.scheduleworld.com/funambol/ds\n"
"peers/scheduleworld/config.ini:username = your SyncML server account name\n"
"peers/scheduleworld/config.ini:password = your SyncML server password\n"
".internal.ini:contextMinVersion = %d\n"
".internal.ini:contextCurVersion = %d\n"
"config.ini:# logdir = \n"
"peers/scheduleworld/config.ini:# loglevel = 0\n"
"peers/scheduleworld/config.ini:# printChanges = 1\n"
"peers/scheduleworld/config.ini:# dumpData = 1\n"
"config.ini:# maxlogdirs = 10\n"
"peers/scheduleworld/config.ini:# autoSync = 0\n"
"peers/scheduleworld/config.ini:# autoSyncInterval = 30M\n"
"peers/scheduleworld/config.ini:# autoSyncDelay = 5M\n"
"peers/scheduleworld/config.ini:# preventSlowSync = 1\n"
"peers/scheduleworld/config.ini:# useProxy = 0\n"
"peers/scheduleworld/config.ini:# proxyHost = \n"
"peers/scheduleworld/config.ini:# proxyUsername = \n"
"peers/scheduleworld/config.ini:# proxyPassword = \n"
"peers/scheduleworld/config.ini:# clientAuthType = md5\n"
"peers/scheduleworld/config.ini:# RetryDuration = 5M\n"
"peers/scheduleworld/config.ini:# RetryInterval = 2M\n"
"peers/scheduleworld/config.ini:# remoteIdentifier = \n"
"peers/scheduleworld/config.ini:# PeerIsClient = 0\n"
"peers/scheduleworld/config.ini:# SyncMLVersion = \n"
"peers/scheduleworld/config.ini:# PeerName = \n"
"config.ini:deviceId = fixed-devid\n" /* this is not the default! */
"peers/scheduleworld/config.ini:# remoteDeviceId = \n"
"peers/scheduleworld/config.ini:# enableWBXML = 1\n"
"peers/scheduleworld/config.ini:# maxMsgSize = 150000\n"
"peers/scheduleworld/config.ini:# maxObjSize = 4000000\n"
"peers/scheduleworld/config.ini:# enableCompression = 0\n"
"peers/scheduleworld/config.ini:# SSLServerCertificates = \n"
"peers/scheduleworld/config.ini:# SSLVerifyServer = 1\n"
"peers/scheduleworld/config.ini:# SSLVerifyHost = 1\n"
"peers/scheduleworld/config.ini:WebURL = http://www.scheduleworld.com\n"
"peers/scheduleworld/config.ini:# IconURI = \n"
"peers/scheduleworld/config.ini:# ConsumerReady = 0\n"
"peers/scheduleworld/sources/addressbook/.internal.ini:# adminData = \n"
"peers/scheduleworld/sources/addressbook/.internal.ini:# synthesisID = 0\n"
"peers/scheduleworld/sources/addressbook/config.ini:sync = two-way\n"
"peers/scheduleworld/sources/addressbook/config.ini:uri = card3\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/addressbook/config.ini:backend = addressbook\n"
"peers/scheduleworld/sources/addressbook/config.ini:syncFormat = text/vcard\n"
"peers/scheduleworld/sources/addressbook/config.ini:# forceSyncFormat = 0\n"
"sources/addressbook/config.ini:# database = \n"
"sources/addressbook/config.ini:# databaseFormat = \n"
"sources/addressbook/config.ini:# databaseUser = \n"
"sources/addressbook/config.ini:# databasePassword = \n"
"peers/scheduleworld/sources/calendar/.internal.ini:# adminData = \n"
"peers/scheduleworld/sources/calendar/.internal.ini:# synthesisID = 0\n"
"peers/scheduleworld/sources/calendar/config.ini:sync = two-way\n"
"peers/scheduleworld/sources/calendar/config.ini:uri = cal2\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/calendar/config.ini:backend = calendar\n"
"peers/scheduleworld/sources/calendar/config.ini:# syncFormat = \n"
"peers/scheduleworld/sources/calendar/config.ini:# forceSyncFormat = 0\n"
"sources/calendar/config.ini:# database = \n"
"sources/calendar/config.ini:# databaseFormat = \n"
"sources/calendar/config.ini:# databaseUser = \n"
"sources/calendar/config.ini:# databasePassword = \n"
"peers/scheduleworld/sources/memo/.internal.ini:# adminData = \n"
"peers/scheduleworld/sources/memo/.internal.ini:# synthesisID = 0\n"
"peers/scheduleworld/sources/memo/config.ini:sync = two-way\n"
"peers/scheduleworld/sources/memo/config.ini:uri = note\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/memo/config.ini:backend = memo\n"
"peers/scheduleworld/sources/memo/config.ini:# syncFormat = \n"
"peers/scheduleworld/sources/memo/config.ini:# forceSyncFormat = 0\n"
"sources/memo/config.ini:# database = \n"
"sources/memo/config.ini:# databaseFormat = \n"
"sources/memo/config.ini:# databaseUser = \n"
"sources/memo/config.ini:# databasePassword = \n"
"peers/scheduleworld/sources/todo/.internal.ini:# adminData = \n"
"peers/scheduleworld/sources/todo/.internal.ini:# synthesisID = 0\n"
"peers/scheduleworld/sources/todo/config.ini:sync = two-way\n"
"peers/scheduleworld/sources/todo/config.ini:uri = task2\n"
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"sources/todo/config.ini:backend = todo\n"
"peers/scheduleworld/sources/todo/config.ini:# syncFormat = \n"
"peers/scheduleworld/sources/todo/config.ini:# forceSyncFormat = 0\n"
"sources/todo/config.ini:# database = \n"
"sources/todo/config.ini:# databaseFormat = \n"
"sources/todo/config.ini:# databaseUser = \n"
"sources/todo/config.ini:# databasePassword = ",
peerMinVersion, peerCurVersion,
contextMinVersion, contextCurVersion);
#ifdef ENABLE_LIBSOUP
// path to SSL certificates has to be set only for libsoup
boost::replace_first(config,
"SSLServerCertificates = ",
"SSLServerCertificates = /etc/ssl/certs/ca-certificates.crt:/etc/pki/tls/certs/ca-bundle.crt:/usr/share/ssl/certs/ca-bundle.crt");
#endif
#if 0
// Currently we don't have an icon for ScheduleWorld. If we
// had (MB #2062) one, then this code would ensure that the
// reference config also has the right path for it.
const char *templateDir = getenv("SYNCEVOLUTION_TEMPLATE_DIR");
if (!templateDir) {
templateDir = TEMPLATE_DIR;
}
if (isDir(string(templateDir) + "/ScheduleWorld")) {
boost::replace_all(config,
"# IconURI = ",
string("IconURI = file://") + templateDir + "/ScheduleWorld/icon.png");
}
#endif
return config;
}
string OldScheduleWorldConfig() {
// old style paths
string oldConfig =
"spds/syncml/config.txt:syncURL = http://sync.scheduleworld.com/funambol/ds\n"
"spds/syncml/config.txt:username = your SyncML server account name\n"
"spds/syncml/config.txt:password = your SyncML server password\n"
"spds/syncml/config.txt:# logdir = \n"
"spds/syncml/config.txt:# loglevel = 0\n"
"spds/syncml/config.txt:# printChanges = 1\n"
"spds/syncml/config.txt:# dumpData = 1\n"
"spds/syncml/config.txt:# maxlogdirs = 10\n"
"spds/syncml/config.txt:# autoSync = 0\n"
"spds/syncml/config.txt:# autoSyncInterval = 30M\n"
"spds/syncml/config.txt:# autoSyncDelay = 5M\n"
"spds/syncml/config.txt:# preventSlowSync = 1\n"
"spds/syncml/config.txt:# useProxy = 0\n"
"spds/syncml/config.txt:# proxyHost = \n"
"spds/syncml/config.txt:# proxyUsername = \n"
"spds/syncml/config.txt:# proxyPassword = \n"
"spds/syncml/config.txt:# clientAuthType = md5\n"
"spds/syncml/config.txt:# RetryDuration = 5M\n"
"spds/syncml/config.txt:# RetryInterval = 2M\n"
"spds/syncml/config.txt:# remoteIdentifier = \n"
"spds/syncml/config.txt:# PeerIsClient = 0\n"
"spds/syncml/config.txt:# SyncMLVersion = \n"
"spds/syncml/config.txt:# PeerName = \n"
"spds/syncml/config.txt:deviceId = fixed-devid\n" /* this is not the default! */
"spds/syncml/config.txt:# remoteDeviceId = \n"
"spds/syncml/config.txt:# enableWBXML = 1\n"
"spds/syncml/config.txt:# maxMsgSize = 150000\n"
"spds/syncml/config.txt:# maxObjSize = 4000000\n"
"spds/syncml/config.txt:# enableCompression = 0\n"
#ifdef ENABLE_LIBSOUP
// path to SSL certificates is only set for libsoup
"spds/syncml/config.txt:# SSLServerCertificates = /etc/ssl/certs/ca-certificates.crt:/etc/pki/tls/certs/ca-bundle.crt:/usr/share/ssl/certs/ca-bundle.crt\n"
#else
"spds/syncml/config.txt:# SSLServerCertificates = \n"
#endif
"spds/syncml/config.txt:# SSLVerifyServer = 1\n"
"spds/syncml/config.txt:# SSLVerifyHost = 1\n"
"spds/syncml/config.txt:WebURL = http://www.scheduleworld.com\n"
"spds/syncml/config.txt:# IconURI = \n"
"spds/syncml/config.txt:# ConsumerReady = 0\n"
"spds/sources/addressbook/config.txt:sync = two-way\n"
"spds/sources/addressbook/config.txt:type = addressbook:text/vcard\n"
"spds/sources/addressbook/config.txt:evolutionsource = xyz\n"
"spds/sources/addressbook/config.txt:uri = card3\n"
"spds/sources/addressbook/config.txt:evolutionuser = foo\n"
"spds/sources/addressbook/config.txt:evolutionpassword = bar\n"
"spds/sources/calendar/config.txt:sync = two-way\n"
"spds/sources/calendar/config.txt:type = calendar\n"
"spds/sources/calendar/config.txt:# database = \n"
"spds/sources/calendar/config.txt:uri = cal2\n"
"spds/sources/calendar/config.txt:# evolutionuser = \n"
"spds/sources/calendar/config.txt:# evolutionpassword = \n"
"spds/sources/memo/config.txt:sync = two-way\n"
"spds/sources/memo/config.txt:type = memo\n"
"spds/sources/memo/config.txt:# database = \n"
"spds/sources/memo/config.txt:uri = note\n"
"spds/sources/memo/config.txt:# evolutionuser = \n"
"spds/sources/memo/config.txt:# evolutionpassword = \n"
"spds/sources/todo/config.txt:sync = two-way\n"
"spds/sources/todo/config.txt:type = todo\n"
"spds/sources/todo/config.txt:# database = \n"
"spds/sources/todo/config.txt:uri = task2\n"
"spds/sources/todo/config.txt:# evolutionuser = \n"
"spds/sources/todo/config.txt:# evolutionpassword = \n";
return oldConfig;
}
string FunambolConfig() {
string config = ScheduleWorldConfig();
boost::replace_all(config, "/scheduleworld/", "/funambol/");
boost::replace_first(config,
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = http://my.funambol.com/sync");
boost::replace_first(config,
"WebURL = http://www.scheduleworld.com",
"WebURL = http://my.funambol.com");
boost::replace_first(config,
"# ConsumerReady = 0",
"ConsumerReady = 1");
boost::replace_first(config,
"# enableWBXML = 1",
"enableWBXML = 0");
boost::replace_first(config,
"# RetryInterval = 2M",
"RetryInterval = 0");
boost::replace_first(config,
"addressbook/config.ini:uri = card3",
"addressbook/config.ini:uri = card");
boost::replace_all(config,
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"addressbook/config.ini:syncFormat = text/vcard",
"addressbook/config.ini:# syncFormat = ");
boost::replace_first(config,
"calendar/config.ini:uri = cal2",
"calendar/config.ini:uri = event");
boost::replace_all(config,
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"calendar/config.ini:# syncFormat = ",
"calendar/config.ini:syncFormat = text/calendar");
boost::replace_all(config,
"calendar/config.ini:# forceSyncFormat = 0",
"calendar/config.ini:forceSyncFormat = 1");
boost::replace_first(config,
"todo/config.ini:uri = task2",
"todo/config.ini:uri = task");
boost::replace_all(config,
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"todo/config.ini:# syncFormat = ",
"todo/config.ini:syncFormat = text/calendar");
boost::replace_all(config,
"todo/config.ini:# forceSyncFormat = 0",
"todo/config.ini:forceSyncFormat = 1");
return config;
}
string SynthesisConfig() {
string config = ScheduleWorldConfig();
boost::replace_all(config, "/scheduleworld/", "/synthesis/");
boost::replace_first(config,
"syncURL = http://sync.scheduleworld.com/funambol/ds",
"syncURL = http://www.synthesis.ch/sync");
boost::replace_first(config,
"WebURL = http://www.scheduleworld.com",
"WebURL = http://www.synthesis.ch");
boost::replace_first(config,
"addressbook/config.ini:uri = card3",
"addressbook/config.ini:uri = contacts");
boost::replace_all(config,
config: replaced overloaded "type" with "backend/databaseFormat/syncFormat/forceSyncFormat" (BMC #1023) The meaning of "type" was horribly complex and had effects on the backend and the peer. It was impossible to specify the sync format to be used for a specific peer independently of the local backend and its format, so adding a peer to a context broke the context configuration (BMC #1023). This is now fixed by splitting "type" into four independent properties: - backend = plugin which interfaces with the data - databaseFormat = data format used inside backend, only relevant for file backend - syncFormat = data format preferred when talking to peer - forceSyncFormat = disable format auto-negotiation, use preferred format With that split, it is now possible to specify the format in which the file backend stores items independently of the format in which they are exchanged with the peer. Old configurations with "type" can still be read. The values specified inside it are transparently mapped to the new properties. Command line and D-Bus API users will only see the new properties. The command line tool still accepts "type" as an alias for the four new properties. Using that has the same disadvantage as before: it will modify the context even if only modifying the peer was intended. The D-Bus API accepts only the new properties. Clients using "type" must be adapted to the new property names. Clients not using that continue to run unchanged. Writing into the configuration requires a migration of the peer config *and* the context in which it is defined. That is necessary because the new semantic (independent database format) cannot be stored in the old format. The migration is handled by rewriting first the context, then all peers defined inside it. Other user-visible changes: - updated help texts - the canonical "backend" value for the file backend is just "file" instead of the long "Files in one directory", which is now an alias (used to be the other way around); done because "type = file" was expanded to the long name, which was a bit unexpected and showed how unintuitive the long name is Internal changes: - getMimeVersion() is still present, although it hasn't been used for a long time; FileSyncSource::getMimeVersion() now derives the version from the supported Mime types, in case that the function will be needed again in the future - setSourceType() with string as argument was replaced with one taking a SourceType instance; to emulate the old behavior if desired, construct SourceType from an old-style string - ConfigProperty methods need to be virtual so that derived classes like SourceBackendConfigProperty can generate content at runtime (a recent commit broke that feature) - File templates were stripped down to the essential properties, with "type" replaced by the per-peer "syncFormat". "type" would still have been accepted (so it is not necessary to adapt syncevo-phone-config right away), but has the original disadvantage of modifying "backend" and "databaseFormat".
2011-02-03 12:17:24 +01:00
"addressbook/config.ini:syncFormat = text/vcard",
"addressbook/config.ini:# syncFormat = ");
boost::replace_first(config,
"calendar/config.ini:uri = cal2",
"calendar/config.ini:uri = events");
boost::replace_first(config,
"calendar/config.ini:sync = two-way",
"calendar/config.ini:sync = disabled");
boost::replace_first(config,
"memo/config.ini:uri = note",
"memo/config.ini:uri = notes");
boost::replace_first(config,
"todo/config.ini:uri = task2",
"todo/config.ini:uri = tasks");
boost::replace_first(config,
"todo/config.ini:sync = two-way",
"todo/config.ini:sync = disabled");
return config;
}
/** create directory hierarchy, overwriting previous content */
void createFiles(const string &root, const string &content, bool append = false) {
if (!append) {
rm_r(root);
}
size_t start = 0;
ofstream out;
string outname;
out.exceptions(ios_base::badbit|ios_base::failbit);
while (start < content.size()) {
size_t delim = content.find(':', start);
size_t end = content.find('\n', start);
if (delim == content.npos ||
end == content.npos) {
// invalid content ?!
break;
}
string newname = content.substr(start, delim - start);
string line = content.substr(delim + 1, end - delim - 1);
if (newname != outname) {
if (out.is_open()) {
out.close();
}
string fullpath = root + "/" + newname;
size_t fileoff = fullpath.rfind('/');
mkdir_p(fullpath.substr(0, fileoff));
out.open(fullpath.c_str(),
append ? ios_base::out : (ios_base::out|ios_base::trunc));
outname = newname;
}
out << line << endl;
start = end + 1;
}
}
/** turn directory hierarchy into string
*
* @param root root path in file system
* @param peer if non-empty, then ignore all <root>/peers/<foo> directories
* where <foo> != peer
* @param onlyProps ignore lines which are comments
*/
string scanFiles(const string &root, const string &peer = "", bool onlyProps = true) {
ostringstream out;
scanFiles(root, "", peer, out, onlyProps);
return out.str();
}
void scanFiles(const string &root, const string &dir, const string &peer, ostringstream &out, bool onlyProps) {
string newroot = root;
newroot += "/";
newroot += dir;
ReadDir readDir(newroot);
sort(readDir.begin(), readDir.end());
BOOST_FOREACH(const string &entry, readDir) {
if (isDir(newroot + "/" + entry)) {
if (boost::ends_with(newroot, "/peers") &&
!peer.empty() &&
entry != peer) {
// skip different peer directory
continue;
} else {
scanFiles(root, dir + (dir.empty() ? "" : "/") + entry, peer, out, onlyProps);
}
} else {
ifstream in;
in.exceptions(ios_base::badbit /* failbit must not trigger exception because is set when reaching eof ?! */);
in.open((newroot + "/" + entry).c_str());
string line;
while (!in.eof()) {
getline(in, line);
if ((line.size() || !in.eof()) &&
(!onlyProps ||
(boost::starts_with(line, "# ") ?
isPropAssignment(line.substr(2)) :
!line.empty()))) {
if (dir.size()) {
out << dir << "/";
}
out << entry << ":";
out << line << '\n';
}
}
}
}
}
string printConfig(const string &server) {
ScopedEnvChange templates("SYNCEVOLUTION_TEMPLATE_DIR", "/dev/null");
ScopedEnvChange xdg("XDG_CONFIG_HOME", m_testDir);
ScopedEnvChange home("HOME", m_testDir);
TestCmdline cmdline("--print-config", server.c_str(), NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF("", cmdline.m_err.str());
return cmdline.m_out.str();
}
};
SYNCEVOLUTION_TEST_SUITE_REGISTRATION(CmdlineTest);
#endif // ENABLE_UNIT_TESTS
SE_END_CXX