added file backend
git-svn-id: https://zeitsenke.de/svn/SyncEvolution/trunk@701 15ad00c4-1369-45f4-8270-35d70d36bdcd
This commit is contained in:
parent
cc4cdb6c56
commit
76491facab
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Patrick Ohly
|
||||
* Copyright (C) 2007 Funambol
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ENABLE_FILE
|
||||
|
||||
#include "FileSyncSource.h"
|
||||
|
||||
// SyncEvolution includes a copy of Boost header files.
|
||||
// They are safe to use without creating additional
|
||||
// build dependencies. boost::filesystem requires a
|
||||
// library and therefore is avoided here. Some
|
||||
// utility functions from SyncEvolution are used
|
||||
// instead, plus standard C/Posix functions.
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <SyncEvolutionUtil.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
FileSyncSource::FileSyncSource(const EvolutionSyncSourceParams ¶ms,
|
||||
const string &dataformat) :
|
||||
TrackingSyncSource(params),
|
||||
m_entryCounter(0)
|
||||
{
|
||||
if (dataformat.empty()) {
|
||||
throwError("a data format must be specified");
|
||||
}
|
||||
size_t sep = dataformat.find(':');
|
||||
if (sep == dataformat.npos) {
|
||||
throwError(string("data format not specified as <mime type>:<mime version>: " + dataformat));
|
||||
}
|
||||
m_mimeType.assign(dataformat, 0, sep);
|
||||
m_mimeVersion = dataformat.substr(sep + 1);
|
||||
m_supportedTypes = dataformat;
|
||||
}
|
||||
|
||||
string FileSyncSource::fileSuffix() const
|
||||
{
|
||||
// database dumps created by SyncEvolution use this file suffix
|
||||
return
|
||||
(m_mimeType == "text/vcard" || m_mimeType == "text/x-vcard") ? "vcf" :
|
||||
(m_mimeType == "text/calendar" || m_mimeType == "text/x-calendar") ? "ics" :
|
||||
(m_mimeType == "text/plain") ? "txt" :
|
||||
"dat";
|
||||
}
|
||||
|
||||
const char *FileSyncSource::getMimeType() const
|
||||
{
|
||||
return m_mimeType.c_str();
|
||||
}
|
||||
|
||||
const char *FileSyncSource::getMimeVersion() const
|
||||
{
|
||||
return m_mimeVersion.c_str();
|
||||
}
|
||||
|
||||
const char *FileSyncSource::getSupportedTypes() const
|
||||
{
|
||||
// comma separated list, like "text/vcard:3.0,text/x-vcard:2.1"
|
||||
return m_supportedTypes.c_str();
|
||||
}
|
||||
|
||||
void FileSyncSource::open()
|
||||
{
|
||||
const string &database = getDatabaseID();
|
||||
const string prefix("file://");
|
||||
string basedir;
|
||||
bool createDir = false;
|
||||
|
||||
// file:// is optional. It indicates that the
|
||||
// directory is to be created.
|
||||
if (boost::starts_with(database, prefix)) {
|
||||
basedir = database.substr(prefix.size());
|
||||
createDir = true;
|
||||
} else {
|
||||
basedir = database;
|
||||
}
|
||||
|
||||
// check and, if allowed and necessary, create it
|
||||
if (!isDir(basedir)) {
|
||||
if (errno == ENOENT && createDir) {
|
||||
mkdir_p(basedir.c_str());
|
||||
} else {
|
||||
throwError(basedir + ": " + strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// success!
|
||||
m_basedir = basedir;
|
||||
}
|
||||
|
||||
void FileSyncSource::close()
|
||||
{
|
||||
m_basedir.clear();
|
||||
}
|
||||
|
||||
FileSyncSource::Databases FileSyncSource::getDatabases()
|
||||
{
|
||||
Databases result;
|
||||
|
||||
result.push_back(Database("select database via directory path",
|
||||
"[file://]<path>"));
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileSyncSource::listAllItems(RevisionMap_t &revisions)
|
||||
{
|
||||
ReadDir dirContent(m_basedir);
|
||||
|
||||
BOOST_FOREACH(const string &entry, dirContent) {
|
||||
string filename = createFilename(entry);
|
||||
string revision = getATimeString(filename);
|
||||
long entrynum = atoll(entry.c_str());
|
||||
if (entrynum >= m_entryCounter) {
|
||||
m_entryCounter = entrynum + 1;
|
||||
}
|
||||
revisions[entry] = revision;
|
||||
}
|
||||
}
|
||||
|
||||
SyncItem *FileSyncSource::createItem(const string &uid)
|
||||
{
|
||||
string filename = createFilename(uid);
|
||||
|
||||
ifstream in;
|
||||
in.open(filename.c_str());
|
||||
ostringstream out;
|
||||
char buf[8192];
|
||||
do {
|
||||
in.read(buf, sizeof(buf));
|
||||
out.write(buf, in.gcount());
|
||||
} while(in);
|
||||
if (!in.good() && !in.eof()) {
|
||||
throwError(filename + ": reading failed");
|
||||
}
|
||||
|
||||
string content = out.str();
|
||||
auto_ptr<SyncItem> item(new SyncItem(uid.c_str()));
|
||||
item->setData(content.c_str(), content.size());
|
||||
item->setDataType(getMimeType());
|
||||
// probably not even used by Funambol client library...
|
||||
item->setModificationTime(0);
|
||||
|
||||
return item.release();
|
||||
}
|
||||
|
||||
TrackingSyncSource::InsertItemResult FileSyncSource::insertItem(const string &uid, const SyncItem &item)
|
||||
{
|
||||
string newuid = uid;
|
||||
string creationTime;
|
||||
string filename;
|
||||
|
||||
// Inserting a new and updating an existing item often uses
|
||||
// very similar code. In this case only the code for determining
|
||||
// the filename differs.
|
||||
//
|
||||
// In other sync sources the database might also have limitations
|
||||
// for the content of different items, for example, only one
|
||||
// VCALENDAR:EVENT with a certain UID. If the server does not
|
||||
// recognize that and sends a new item which collides with an
|
||||
// existing one, then the existing one should be updated.
|
||||
|
||||
if (uid.size()) {
|
||||
// valid local ID: update that file
|
||||
filename = createFilename(uid);
|
||||
} else {
|
||||
// no local ID: create new file
|
||||
while (true) {
|
||||
ostringstream buff;
|
||||
buff << m_entryCounter;
|
||||
filename = createFilename(buff.str());
|
||||
|
||||
// only create and truncate if file does not
|
||||
// exist yet, otherwise retry with next counter
|
||||
struct stat dummy;
|
||||
if (stat(filename.c_str(), &dummy)) {
|
||||
if (errno == ENOENT) {
|
||||
newuid = buff.str();
|
||||
break;
|
||||
} else {
|
||||
throwError(filename + ": " + strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
m_entryCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
ofstream out;
|
||||
out.open(filename.c_str());
|
||||
out.write((const char *)item.getData(), item.getDataSize());
|
||||
out.close();
|
||||
if (!out.good()) {
|
||||
throwError(filename + ": writing failed");
|
||||
}
|
||||
|
||||
return InsertItemResult(newuid,
|
||||
getATimeString(filename),
|
||||
false /* true if adding item was turned into update */);
|
||||
}
|
||||
|
||||
|
||||
void FileSyncSource::deleteItem(const string &uid)
|
||||
{
|
||||
string filename = createFilename(uid);
|
||||
|
||||
if (unlink(filename.c_str())) {
|
||||
throwError(filename + ": " + strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void FileSyncSource::flush()
|
||||
{
|
||||
// Our change tracking is time based.
|
||||
// Don't let caller proceed without waiting for
|
||||
// one second to prevent being called again before
|
||||
// the modification time stamp is larger than it
|
||||
// is now.
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
void FileSyncSource::logItem(const string &uid, const string &info, bool debug)
|
||||
{
|
||||
if (LOG.getLevel() >= (debug ? LOG_LEVEL_DEBUG : LOG_LEVEL_INFO)) {
|
||||
// If there was a good way to extract a short string identifying
|
||||
// the item with uid, we would use it here and log it like this:
|
||||
// (LOG.*(debug ? &Log::debug : &Log::info))("%s: %s %s",
|
||||
// getName() /* out sync source name */,
|
||||
// itemName,
|
||||
// info.c_str());
|
||||
//
|
||||
// Alternatively we could just log the uid. EvolutionSyncSource::logItem()
|
||||
// is an utility function which extracts a short string from certain
|
||||
// well-known types (FN for vCard, SUMMARY for vCalendar, first line for
|
||||
// text, ...). We use it here although it requires reading the full item
|
||||
// first. Don't fail while reading, we'll trigger a real error later on
|
||||
// if necessary.
|
||||
|
||||
string filename = createFilename(uid);
|
||||
|
||||
ifstream in;
|
||||
in.open(filename.c_str());
|
||||
ostringstream out;
|
||||
char buf[8192];
|
||||
do {
|
||||
in.read(buf, sizeof(buf));
|
||||
out.write(buf, in.gcount());
|
||||
} while(in);
|
||||
logItemUtil(out.str(),
|
||||
m_mimeType,
|
||||
m_mimeVersion,
|
||||
uid,
|
||||
info,
|
||||
debug);
|
||||
}
|
||||
}
|
||||
|
||||
void FileSyncSource::logItem(const SyncItem &item, const string &info, bool debug)
|
||||
{
|
||||
if (LOG.getLevel() >= (debug ? LOG_LEVEL_DEBUG : LOG_LEVEL_INFO)) {
|
||||
if (!item.getData()) {
|
||||
// operation on item without data, fall back to logging via uid
|
||||
logItem(string(item.getKey()), info, debug);
|
||||
} else {
|
||||
string data = (const char *)item.getData();
|
||||
|
||||
logItemUtil(data,
|
||||
m_mimeType,
|
||||
m_mimeVersion,
|
||||
item.getKey(),
|
||||
info,
|
||||
debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string FileSyncSource::getATimeString(const string &filename)
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(filename.c_str(), &buf)) {
|
||||
throwError(filename + ": " + strerror(errno));
|
||||
}
|
||||
time_t mtime = buf.st_mtime;
|
||||
|
||||
ostringstream revision;
|
||||
revision << mtime;
|
||||
|
||||
return revision.str();
|
||||
}
|
||||
|
||||
string FileSyncSource::createFilename(const string &entry)
|
||||
{
|
||||
string filename = m_basedir + "/" + entry;
|
||||
return filename;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_FILE */
|
||||
|
||||
#ifdef ENABLE_MODULES
|
||||
# include "FileSyncSourceRegister.cpp"
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Patrick Ohly
|
||||
* Copyright (C) 2007 Funambol
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef INCL_FILESYNCSOURCE
|
||||
#define INCL_FILESYNCSOURCE
|
||||
|
||||
#include "TrackingSyncSource.h"
|
||||
|
||||
#ifdef ENABLE_FILE
|
||||
|
||||
#include <memory>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
/**
|
||||
* Stores each SyncML item as a separate file in a directory. The
|
||||
* directory has to be specified via the database name, using
|
||||
* [file://]<path> as format. The file:// prefix is optional, but the
|
||||
* directory is only created if it is used.
|
||||
* EvolutionSyncSource::getDatabaseID() gives us the database name.
|
||||
*
|
||||
* Change tracking is done via the file systems modification time
|
||||
* stamp: editing a file treats it as modified and then sends it to
|
||||
* the server in the next sync. Removing and adding files also works.
|
||||
*
|
||||
* The local unique identifier for each item is its name in the
|
||||
* directory. New files are created using a running count which
|
||||
* initialized based on the initial content of the directory to
|
||||
* "highest existing number + 1" and incremented to avoid collisions.
|
||||
*
|
||||
* Although this sync source itself does not care about the content of
|
||||
* each item/file, the server needs to know what each item sent to it
|
||||
* contains and what items the source is able to receive. Therefore
|
||||
* the "type" property for this source must contain a data format
|
||||
* specified, including a version for it. Here are some examples:
|
||||
* - type=file:text/vcard:3.0
|
||||
* - type=file:text/plain:1.0
|
||||
*/
|
||||
class FileSyncSource : public TrackingSyncSource, private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
FileSyncSource(const EvolutionSyncSourceParams ¶ms,
|
||||
const string &dataformat);
|
||||
|
||||
|
||||
protected:
|
||||
/* implementation of EvolutionSyncSource interface */
|
||||
virtual void open();
|
||||
virtual void close();
|
||||
virtual Databases getDatabases();
|
||||
virtual SyncItem *createItem(const string &uid);
|
||||
virtual string fileSuffix() const;
|
||||
virtual const char *getMimeType() const;
|
||||
virtual const char *getMimeVersion() const;
|
||||
virtual const char *getSupportedTypes() const;
|
||||
virtual void logItem(const string &uid, const string &info, bool debug = false);
|
||||
virtual void logItem(const SyncItem &item, const string &info, bool debug = false);
|
||||
|
||||
/* implementation of TrackingSyncSource interface */
|
||||
virtual void listAllItems(RevisionMap_t &revisions);
|
||||
virtual InsertItemResult insertItem(const string &uid, const SyncItem &item);
|
||||
virtual void deleteItem(const string &uid);
|
||||
virtual void flush();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @name values obtained from the source's type property
|
||||
*
|
||||
* Other sync sources only support one hard-coded type and
|
||||
* don't need such variables.
|
||||
*/
|
||||
/**@{*/
|
||||
string m_mimeType;
|
||||
string m_mimeVersion;
|
||||
string m_supportedTypes;
|
||||
/**@}*/
|
||||
|
||||
/** directory selected via the database name in open(), reset in close() */
|
||||
string m_basedir;
|
||||
/** a counter which is used to name new files */
|
||||
long m_entryCounter;
|
||||
|
||||
/**
|
||||
* get access time for file, formatted as revision string
|
||||
* @param filename absolute path or path relative to current directory
|
||||
*/
|
||||
string getATimeString(const string &filename);
|
||||
|
||||
/**
|
||||
* create full filename from basedir and entry name
|
||||
*/
|
||||
string createFilename(const string &entry);
|
||||
};
|
||||
|
||||
#endif // ENABLE_FILE
|
||||
#endif // INCL_FILESYNCSOURCE
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Patrick Ohly
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "FileSyncSource.h"
|
||||
|
||||
// The anonymous namespace ensures that we don't get
|
||||
// name clashes: although the classes and objects are
|
||||
// only defined in this file, the methods generated
|
||||
// for local classes will clash with other methods
|
||||
// of other classes with the same name if no namespace
|
||||
// is used.
|
||||
namespace {
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
|
||||
static EvolutionSyncSource *createSource(const EvolutionSyncSourceParams ¶ms)
|
||||
{
|
||||
pair <string, string> sourceType = EvolutionSyncSource::getSourceType(params.m_nodes);
|
||||
// The string returned by getSourceType() is always the one
|
||||
// registered as main Aliases() below.
|
||||
bool isMe = sourceType.first == "Files in one directory";
|
||||
|
||||
#ifndef ENABLE_FILE
|
||||
// tell SyncEvolution if the user wanted to use a disabled sync source,
|
||||
// otherwise let it continue searching
|
||||
return isMe ? RegisterSyncSource::InactiveSource : NULL;
|
||||
#else
|
||||
// Also recognize one of the standard types?
|
||||
// Not in the FileSyncSource!
|
||||
bool maybeMe = false /* sourceType.first == "addressbook" */;
|
||||
|
||||
if (isMe || maybeMe) {
|
||||
// The FileSyncSource always needs the data format
|
||||
// parameter in sourceType.second.
|
||||
if (/* sourceType.second == "" || sourceType.second == "text/x-vcard" */
|
||||
sourceType.second.size()) {
|
||||
return new FileSyncSource(params, sourceType.second);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static RegisterSyncSource registerMe("Files in one directory",
|
||||
#ifdef ENABLE_FILE
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
createSource,
|
||||
"Files in one directory = file\n"
|
||||
" Stores items in one directory as one file per item.\n"
|
||||
" The directory is selected via [file://]<path>; it\n"
|
||||
" will only be created if the prefix is given, otherwise\n"
|
||||
" it must exist already. Only items of the same type can\n"
|
||||
" be synchronized and this type must be specified explicitly\n"
|
||||
" with both mime type and version.\n"
|
||||
" Examples:\n"
|
||||
" file:text/plain:1.0\n"
|
||||
" file:text/x-vcard:2.1\n"
|
||||
" file:text/vcard:3.0\n"
|
||||
" file:text/x-calendar:1.0\n"
|
||||
" file:text/calendar:2.0\n",
|
||||
Values() +
|
||||
(Aliases("Files in one directory") + "file"));
|
||||
|
||||
#ifdef ENABLE_FILE
|
||||
#ifdef ENABLE_UNIT_TESTS
|
||||
|
||||
class FileSyncSourceUnitTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(FileSyncSourceUnitTest);
|
||||
CPPUNIT_TEST(testInstantiate);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
protected:
|
||||
void testInstantiate() {
|
||||
boost::shared_ptr<EvolutionSyncSource> source;
|
||||
source.reset(EvolutionSyncSource::createTestingSource("file", "file:text/vcard:3.0", true));
|
||||
source.reset(EvolutionSyncSource::createTestingSource("file", "file:text/plain:1.0", true));
|
||||
source.reset(EvolutionSyncSource::createTestingSource("file", "Files in one directory:text/x-vcard:2.1", true));
|
||||
}
|
||||
};
|
||||
|
||||
SYNCEVOLUTION_TEST_SUITE_REGISTRATION(FileSyncSourceUnitTest);
|
||||
|
||||
#endif // ENABLE_UNIT_TESTS
|
||||
|
||||
#ifdef ENABLE_INTEGRATION_TESTS
|
||||
static class FileSyncSourceVCard21Test : public RegisterSyncSourceTest {
|
||||
public:
|
||||
FileSyncSourceVCard21Test() : RegisterSyncSourceTest("file_vcard21", "vcard21") {}
|
||||
|
||||
virtual void updateConfig(ClientTestConfig &config) const
|
||||
{
|
||||
// set type as required by FileSyncSource
|
||||
// and leave everything else at its default
|
||||
config.type = "file:text/x-vcard:2.1";
|
||||
}
|
||||
} FileSyncSourceVCard21Test;
|
||||
|
||||
static class FileSyncSourceVCard30Test : public RegisterSyncSourceTest {
|
||||
public:
|
||||
FileSyncSourceVCard30Test() : RegisterSyncSourceTest("file_vcard30", "vcard30") {}
|
||||
|
||||
virtual void updateConfig(ClientTestConfig &config) const
|
||||
{
|
||||
config.type = "file:text/vcard:3.0";
|
||||
}
|
||||
} FileSyncSourceVCard30Test;
|
||||
|
||||
static class FileSyncSourceICal20Test : public RegisterSyncSourceTest {
|
||||
public:
|
||||
FileSyncSourceICal20Test() : RegisterSyncSourceTest("file_ical20", "ical20") {}
|
||||
|
||||
virtual void updateConfig(ClientTestConfig &config) const
|
||||
{
|
||||
config.type = "file:text/calendar:2.0";
|
||||
}
|
||||
} FileSyncSourceICal20Test;
|
||||
|
||||
static class FileSyncSourceITodo20Test : public RegisterSyncSourceTest {
|
||||
public:
|
||||
FileSyncSourceITodo20Test() : RegisterSyncSourceTest("file_itodo20", "itodo20") {}
|
||||
|
||||
virtual void updateConfig(ClientTestConfig &config) const
|
||||
{
|
||||
config.type = "file:text/calendar:2.0";
|
||||
}
|
||||
} FileSyncSourceITodo20Test;
|
||||
|
||||
#endif // ENABLE_INTEGRATION_TESTS
|
||||
|
||||
#endif // ENABLE_FILE
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
# Some of the core header files still have a dependency on Evolution,
|
||||
# which is why its flags have to be listed. They are empty if Evolution
|
||||
# access is disabled.
|
||||
AM_CPPFLAGS = -I$(srcdir)/../../core @EPACKAGE_CFLAGS@ @EBOOK_CFLAGS@ @ECAL_CFLAGS@ @FILE_CFLAGS@ @FUNAMBOL_CFLAGS@
|
||||
|
||||
# Applies to sources in SyncEvolution repository, but not
|
||||
# the Funambol C++ client library. Used to add -Wall -Werror
|
||||
# only when compiling that source, but not for the client
|
||||
# library.
|
||||
SYNCEVOLUTION_CXXFLAGS = @SYNCEVOLUTION_CXXFLAGS@
|
||||
|
||||
EXTRA_DIST = configure-sub.in
|
||||
|
||||
SYNCSOURCES = syncfile.la
|
||||
MOSTLYCLEANFILES = $(SYNCSOURCES)
|
||||
if ENABLE_MODULES
|
||||
pkglib_LTLIBRARIES = $(SYNCSOURCES)
|
||||
else
|
||||
noinst_LTLIBRARIES = $(SYNCSOURCES)
|
||||
endif
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
SYNCFILE_SOURCES = \
|
||||
FileSyncSource.h \
|
||||
FileSyncSource.cpp
|
||||
|
||||
syncfile_la_SOURCES = $(SYNCFILE_SOURCES)
|
||||
syncfile_la_LIBADD = @FILE_LIBS@
|
||||
syncfile_la_LDFLAGS = -module -rpath '$(pkglibdir)'
|
||||
syncfile_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
|
||||
|
||||
# If you need special test cases for your sync source, then
|
||||
# install them here. Here's how the sqlite backend does that:
|
||||
#
|
||||
#../../testcases/sqlite_vcard21.vcf: $(FUNAMBOL_SUBDIR)/test/test/testcases/vcard21.vcf
|
||||
# mkdir -p ${@D}
|
||||
# perl -e '$$_ = join("", <>); s/^(ADR|TEL|EMAIL|PHOTO).*?(?=^\S)//msg; s/;X-EVOLUTION-UI-SLOT=\d+//g; print;' $< >$@
|
||||
#all: ../../testcases/sqlite_vcard21.vcf
|
|
@ -0,0 +1,37 @@
|
|||
dnl -*- mode: Autoconf; -*-
|
||||
dnl Invoke autogen.sh to produce a configure script.
|
||||
|
||||
dnl Checks for required libraris can go here; none required for simple files.
|
||||
dnl
|
||||
dnl This is from the sqlite backend:
|
||||
dnl PKG_CHECK_MODULES(SQLITE, sqlite3, SQLITEFOUND=yes, [SQLITEFOUND=no])
|
||||
dnl AC_SUBST(SQLITE_CFLAGS)
|
||||
dnl AC_SUBST(SQLITE_LIBS)
|
||||
|
||||
FILE_CFLAGS=
|
||||
FILE_LIBS=
|
||||
AC_SUBST(FILE_CFLAGS)
|
||||
AC_SUBST(FILE_LIBS)
|
||||
|
||||
dnl If additional compile flags are necessary to include the header
|
||||
dnl files of the backend, then add them here.
|
||||
BACKEND_CPPFLAGS="$BACKEND_CPPFLAGS $FILE_CFLAGS"
|
||||
|
||||
dnl name of backend library (there could be more than one per directory),
|
||||
dnl name of the directory,
|
||||
dnl help string,
|
||||
dnl --enable/disable chosen explicitly
|
||||
dnl default, may depend on availability of prerequisites in more complex backends
|
||||
AC_ARG_ENABLE_BACKEND(file,
|
||||
file,
|
||||
AS_HELP_STRING([--disable-file],
|
||||
[disable file-based backend which stores items in separate files in a fixed directory (default on)]),
|
||||
[enable_file="$enableval"],
|
||||
[enable_file="yes"]
|
||||
)
|
||||
|
||||
if test "$enable_file" = "yes"; then
|
||||
dnl It's good to check the prerequisites here, in case --enable-file was used.
|
||||
dnl test "x${SQLITEFOUND}" == "xyes" || AC_MSG_ERROR([--enable-sqlite requires pkg-config information for sqlite3, which was not found])
|
||||
AC_DEFINE(ENABLE_FILE, 1, [file available])
|
||||
fi
|
Loading…
Reference in New Issue