summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2014-12-11 03:36:51 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2014-12-11 03:36:51 +0000
commitb6abb83b6e36ee9735a5c34b33e38c878aa233fb (patch)
treec1eb5f837b9a48bec448dd42b8edafb73378f68d
parentSupport complex types in rows and parameters (diff)
downloadproject2-b6abb83b6e36ee9735a5c34b33e38c878aa233fb.tar.bz2
project2-b6abb83b6e36ee9735a5c34b33e38c878aa233fb.tar.xz
project2-b6abb83b6e36ee9735a5c34b33e38c878aa233fb.zip
Use time based logic controlled from OptionsSource to determine if configurations need reloading and if loading was successful
-rw-r--r--project2/cli/claOptions.cpp9
-rw-r--r--project2/cli/claOptions.h4
-rw-r--r--project2/common/optionsSource.cpp21
-rw-r--r--project2/common/optionsSource.h6
-rw-r--r--project2/files/.ycm_extra_conf.py117
-rw-r--r--project2/files/optionsSource.cpp37
-rw-r--r--project2/files/optionsSource.h13
-rw-r--r--project2/ut/testOptionsSource.cpp7
-rw-r--r--project2/ut/testOptionsSource.h3
9 files changed, 171 insertions, 46 deletions
diff --git a/project2/cli/claOptions.cpp b/project2/cli/claOptions.cpp
index b1e1250..da6121d 100644
--- a/project2/cli/claOptions.cpp
+++ b/project2/cli/claOptions.cpp
@@ -12,7 +12,7 @@ CommandLineArguments::CommandLineArguments(int c, const char * const * v, const
argc(c),
argv(v),
others(o),
- loadedAt(0)
+ createdAt(boost::posix_time::microsec_clock::universal_time())
{
}
@@ -76,12 +76,11 @@ CommandLineArguments::loadInto(const ConfigConsumer & consume, const Options::Cu
others(argv[x]);
}
}
- time(&loadedAt);
}
-bool
-CommandLineArguments::needReload() const
+boost::posix_time::ptime
+CommandLineArguments::modifiedTime() const
{
- return !loadedAt;
+ return createdAt;
}
diff --git a/project2/cli/claOptions.h b/project2/cli/claOptions.h
index c669004..3f13b4b 100644
--- a/project2/cli/claOptions.h
+++ b/project2/cli/claOptions.h
@@ -8,13 +8,13 @@ class CommandLineArguments : public OptionsSource {
typedef boost::function<void(const char * const)> Others;
CommandLineArguments(int c, const char * const * v, const Others &);
void loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const;
- bool needReload() const;
+ boost::posix_time::ptime modifiedTime() const override;
private:
const int argc;
const char * const * argv;
const Others others;
- mutable time_t loadedAt;
+ const boost::posix_time::ptime createdAt;
};
#endif
diff --git a/project2/common/optionsSource.cpp b/project2/common/optionsSource.cpp
index 85aebb1..1665557 100644
--- a/project2/common/optionsSource.cpp
+++ b/project2/common/optionsSource.cpp
@@ -20,11 +20,14 @@ class DefaultConfigConsumer : public ConfigConsumer {
}
};
+
+boost::posix_time::ptime OptionsSource::loadedTime = boost::posix_time::special_values::neg_infin;
+
void
OptionsSource::loadSources(const Options::CurrentPlatform & platform)
{
const auto & configs = InstanceSet<OptionsSource>::GetAll();
- if (std::find_if(configs.begin(), configs.end(), boost::bind(&OptionsSource::needReload, _1)) != configs.end()) {
+ if (std::find_if(configs.begin(), configs.end(), [](const OptionsSourcePtr & c) { return c->modifiedTime() > loadedTime; }) != configs.end()) {
InstanceSet<Options>::OnAll(boost::bind(&Options::reset, _1));
DefaultConfigConsumer dcc;
@@ -39,20 +42,22 @@ OptionsSource::loadSources(const Options::CurrentPlatform & platform)
}
Plugable::onAllComponents(boost::bind(&ComponentLoader::onConfigLoad, _1));
- Logger()->message(LOG_DEBUG, "Loaded configuration");
+ loadedTime = boost::posix_time::microsec_clock::universal_time();
+ Logger()->messagebf(LOG_DEBUG, "Loaded configuration at %s", loadedTime);
}
}
void
OptionsSource::loadSource(const Options::CurrentPlatform & platform, OptionsSourcePtr opts)
{
- InstanceSet<Options>::OnAll(boost::bind(&Options::reset, _1));
+ InstanceSet<Options>::OnAll(boost::bind(&Options::reset, _1));
- DefaultConfigConsumer dcc;
- opts->loadInto(dcc, platform);
- Plugable::onAllComponents(boost::bind(&ComponentLoader::onConfigLoad, _1));
-
- Logger()->message(LOG_DEBUG, "Loaded configuration");
+ DefaultConfigConsumer dcc;
+ opts->loadInto(dcc, platform);
+ Plugable::onAllComponents(boost::bind(&ComponentLoader::onConfigLoad, _1));
+
+ loadedTime = boost::posix_time::microsec_clock::universal_time();
+ Logger()->messagebf(LOG_DEBUG, "Loaded configuration at %s", loadedTime);
}
INSTANTIATESTORE(std::string, OptionsSource);
diff --git a/project2/common/optionsSource.h b/project2/common/optionsSource.h
index 6cfbce9..4e0792b 100644
--- a/project2/common/optionsSource.h
+++ b/project2/common/optionsSource.h
@@ -2,6 +2,7 @@
#define OPTIONSSOURCE_H
#include <boost/function.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <glibmm/ustring.h>
#include <intrusivePtrBase.h>
#include "scriptLoader.h"
@@ -20,10 +21,13 @@ typedef boost::shared_ptr<OptionsSource> OptionsSourcePtr;
class OptionsSource {
public:
virtual void loadInto(const ConfigConsumer &, const Options::CurrentPlatform & platform) const = 0;
- virtual bool needReload() const = 0;
+ virtual boost::posix_time::ptime modifiedTime() const = 0;
static void loadSources(const Options::CurrentPlatform & platform);
static void loadSource(const Options::CurrentPlatform & platform, OptionsSourcePtr opts);
+
+ private:
+ static boost::posix_time::ptime loadedTime;
};
typedef PluginsSameBase<OptionsSource, std::string> OptionsSources;
diff --git a/project2/files/.ycm_extra_conf.py b/project2/files/.ycm_extra_conf.py
new file mode 100644
index 0000000..e4f4c84
--- /dev/null
+++ b/project2/files/.ycm_extra_conf.py
@@ -0,0 +1,117 @@
+import os
+import ycm_core
+
+flags = [
+'-Wall',
+'-Wextra',
+'-Werror',
+'-Wc++98-compat',
+'-Wno-long-long',
+'-Wno-variadic-macros',
+'-fexceptions',
+'-DNDEBUG',
+'-std=c++11',
+'-x',
+'c++',
+'-I',
+'.',
+'-I',
+'../common',
+'-I',
+'../lib',
+'-isystem',
+'/usr/include',
+'-isystem',
+'/usr/include/glibmm-2.4',
+]
+
+# Set this to the absolute path to the folder (NOT the file!) containing the
+# compile_commands.json file to use that instead of 'flags'. See here for
+# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
+#
+# Most projects will NOT need to set this to anything; you can just change the
+# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
+compilation_database_folder = ''
+
+if os.path.exists( compilation_database_folder ):
+ database = ycm_core.CompilationDatabase( compilation_database_folder )
+else:
+ database = None
+
+SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
+
+def DirectoryOfThisScript():
+ return os.path.dirname( os.path.abspath( __file__ ) )
+
+
+def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
+ if not working_directory:
+ return list( flags )
+ new_flags = []
+ make_next_absolute = False
+ path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
+ for flag in flags:
+ new_flag = flag
+
+ if make_next_absolute:
+ make_next_absolute = False
+ if not flag.startswith( '/' ):
+ new_flag = os.path.join( working_directory, flag )
+
+ for path_flag in path_flags:
+ if flag == path_flag:
+ make_next_absolute = True
+ break
+
+ if flag.startswith( path_flag ):
+ path = flag[ len( path_flag ): ]
+ new_flag = path_flag + os.path.join( working_directory, path )
+ break
+
+ if new_flag:
+ new_flags.append( new_flag )
+ return new_flags
+
+
+def IsHeaderFile( filename ):
+ extension = os.path.splitext( filename )[ 1 ]
+ return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
+
+
+def GetCompilationInfoForFile( filename ):
+ # The compilation_commands.json file generated by CMake does not have entries
+ # for header files. So we do our best by asking the db for flags for a
+ # corresponding source file, if any. If one exists, the flags for that file
+ # should be good enough.
+ if IsHeaderFile( filename ):
+ basename = os.path.splitext( filename )[ 0 ]
+ for extension in SOURCE_EXTENSIONS:
+ replacement_file = basename + extension
+ if os.path.exists( replacement_file ):
+ compilation_info = database.GetCompilationInfoForFile(
+ replacement_file )
+ if compilation_info.compiler_flags_:
+ return compilation_info
+ return None
+ return database.GetCompilationInfoForFile( filename )
+
+
+def FlagsForFile( filename, **kwargs ):
+ if database:
+ # Bear in mind that compilation_info.compiler_flags_ does NOT return a
+ # python list, but a "list-like" StringVec object
+ compilation_info = GetCompilationInfoForFile( filename )
+ if not compilation_info:
+ return None
+
+ final_flags = MakeRelativePathsInFlagsAbsolute(
+ compilation_info.compiler_flags_,
+ compilation_info.compiler_working_dir_ )
+ else:
+ relative_to = DirectoryOfThisScript()
+ final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
+
+ return {
+ 'flags': final_flags,
+ 'do_cache': True
+ }
diff --git a/project2/files/optionsSource.cpp b/project2/files/optionsSource.cpp
index bb8c549..ed78be4 100644
--- a/project2/files/optionsSource.cpp
+++ b/project2/files/optionsSource.cpp
@@ -1,20 +1,20 @@
#include <pch.hpp>
-#include <sys/stat.h>
+#include <boost/filesystem/convenience.hpp>
#include "optionsSource.h"
#include <glibmm/iochannel.h>
#include <glibmm/fileutils.h>
#include <boost/algorithm/string/trim.hpp>
-FileOptions::FileOptions(const Glib::ustring & f) :
- file(f),
- loadedAt(0)
+FileOptions::FileOptions(const boost::filesystem::path & f) :
+ file(boost::filesystem::current_path() / f)
{
}
void
-FileOptions::loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const {
- try {
- Glib::RefPtr<Glib::IOChannel> cfg = Glib::IOChannel::create_from_file(file, "r");
+FileOptions::loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const
+{
+ if (boost::filesystem::exists(file)) {
+ Glib::RefPtr<Glib::IOChannel> cfg = Glib::IOChannel::create_from_file(file.string(), "r");
Glib::ustring line;
Glib::ustring prefix;
while (cfg->read_line(line) != Glib::IO_STATUS_EOF) {
@@ -50,23 +50,18 @@ FileOptions::loadInto(const ConfigConsumer & consume, const Options::CurrentPlat
break;
}
}
- struct stat st;
- if (stat(file.c_str(), &st) == 0) {
- loadedAt = st.st_mtime;
- }
- }
- catch (const Glib::FileError &) {
}
}
-bool
-FileOptions::needReload() const
+boost::posix_time::ptime
+FileOptions::modifiedTime() const
{
- struct stat st;
- if (stat(file.c_str(), &st) != 0) {
- return true;
- }
- return (loadedAt != st.st_mtime);
+ return boost::posix_time::from_time_t(
+ boost::filesystem::exists(file) ?
+ std::max(
+ boost::filesystem::last_write_time(file),
+ boost::filesystem::last_write_time(file.parent_path())) :
+ boost::filesystem::last_write_time(file.parent_path()));
}
FileOptions::ExtraFileOptions FileOptions::extraFileOptions;
@@ -77,7 +72,7 @@ DECLARE_OPTIONSSOURCE("Z_configfile", new FileOptions(".p2config"))
DECLARE_OPTIONS(FileOptions, "File Options options")
("file.options.read", Options::functions(
[](const VariableType & vt) {
- auto fo = new FileOptions(vt);
+ auto fo = new FileOptions(vt.as<std::string>());
extraFileOptions[vt] = boost::shared_ptr<FileOptions>(fo);
OptionsSources::Add(vt, fo);
},
diff --git a/project2/files/optionsSource.h b/project2/files/optionsSource.h
index 6f25459..a6d1cd1 100644
--- a/project2/files/optionsSource.h
+++ b/project2/files/optionsSource.h
@@ -3,20 +3,23 @@
#include "../common/optionsSource.h"
#include "../common/options.h"
+#include <boost/filesystem/path.hpp>
+
+class FileOptions;
+typedef boost::shared_ptr<FileOptions> FileOptionsPtr;
class FileOptions : public OptionsSource {
public:
- FileOptions(const Glib::ustring & file);
+ FileOptions(const boost::filesystem::path & file);
void loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const;
- bool needReload() const;
+ boost::posix_time::ptime modifiedTime() const override;
INITOPTIONS;
private:
- const Glib::ustring file;
- mutable time_t loadedAt;
+ const boost::filesystem::path file;
- typedef std::map<std::string, boost::shared_ptr<FileOptions>> ExtraFileOptions;
+ typedef std::map<std::string, FileOptionsPtr> ExtraFileOptions;
static ExtraFileOptions extraFileOptions;
};
diff --git a/project2/ut/testOptionsSource.cpp b/project2/ut/testOptionsSource.cpp
index 59dc882..41a05fd 100644
--- a/project2/ut/testOptionsSource.cpp
+++ b/project2/ut/testOptionsSource.cpp
@@ -3,6 +3,7 @@
const Glib::ustring testPlatform;
TestOptionsSource::TestOptionsSource(const Opts & o) :
+ createdAt(boost::posix_time::microsec_clock::universal_time()),
opts(o)
{
}
@@ -15,10 +16,10 @@ TestOptionsSource::loadInto(const ConfigConsumer & consume, const Options::Curre
}
}
-bool
-TestOptionsSource::needReload() const
+boost::posix_time::ptime
+TestOptionsSource::modifiedTime() const
{
- return true;
+ return createdAt;
}
void
diff --git a/project2/ut/testOptionsSource.h b/project2/ut/testOptionsSource.h
index 9bc2101..3d0e046 100644
--- a/project2/ut/testOptionsSource.h
+++ b/project2/ut/testOptionsSource.h
@@ -8,12 +8,13 @@ class TestOptionsSource : public OptionsSource {
typedef std::list<std::pair<std::string, std::string>> Opts;
void loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const override;
- bool needReload() const override;
+ boost::posix_time::ptime modifiedTime() const override;
static void LoadTestOptions(const Opts & o);
private:
TestOptionsSource(const Opts & o);
+ const boost::posix_time::ptime createdAt;
const Opts opts;
};