aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-03-31 20:44:46 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-03-31 20:44:46 +0000
commit30b7f3701998df63f244dbb2c8455245355c99d0 (patch)
treecb0df8e17357f553d0180410b54ca2b94a92e698
parente6016d11e034d8fb85a500f919a588bd6ac09ee8 (diff)
downloadpaludis-30b7f3701998df63f244dbb2c8455245355c99d0.tar.gz
paludis-30b7f3701998df63f244dbb2c8455245355c99d0.tar.xz
Support 'source' in kv
-rw-r--r--paludis/config_file.cc53
-rw-r--r--paludis/config_file_TEST.cc24
-rwxr-xr-xpaludis/config_file_TEST_setup.sh17
3 files changed, 82 insertions, 12 deletions
diff --git a/paludis/config_file.cc b/paludis/config_file.cc
index eb8e87f..0e88a66 100644
--- a/paludis/config_file.cc
+++ b/paludis/config_file.cc
@@ -546,23 +546,38 @@ namespace
}
}
-KeyValueConfigFile::KeyValueConfigFile(const Source & s, const Defaults & d,
+KeyValueConfigFile::KeyValueConfigFile(const Source & ss, const Defaults & d,
bool (* i) (const std::string &, const KeyValueConfigFile &)) :
- ConfigFile(s),
+ ConfigFile(ss),
PrivateImplementationPattern<KeyValueConfigFile>(new Implementation<KeyValueConfigFile>(d, i))
{
- Context context("When parsing key/value configuration file" + (s.filename().empty() ? ":" :
- "'" + s.filename() + "':"));
+ Context context("When parsing key/value configuration file" + (ss.filename().empty() ? ":" :
+ "'" + ss.filename() + "':"));
- std::copy(d.begin(), d.end(), std::inserter(_imp->keys, _imp->keys.begin()));
+ if (! ss.stream())
+ throw ConfigFileError(ss.filename(), "Cannot read input");
- if (! s.stream())
- throw ConfigFileError(s.filename(), "Cannot read input");
+ std::list<std::pair<Source, std::istreambuf_iterator<char> > > sources;
+ sources.push_back(std::make_pair(ss, std::istreambuf_iterator<char>(ss.stream())));
+
+ std::copy(d.begin(), d.end(), std::inserter(_imp->keys, _imp->keys.begin()));
- std::istreambuf_iterator<char> c(s.stream()), c_end;
+ std::istreambuf_iterator<char> c_end;
- while (c != c_end)
+ while ((sources.back().second != c_end) || (! sources.empty()))
{
+ if (sources.back().second == c_end)
+ {
+ sources.pop_back();
+ if (sources.empty())
+ break;
+ else
+ continue;
+ }
+
+ Source & s(sources.back().first);
+ std::istreambuf_iterator<char> & c(sources.back().second);
+
if (*c == '#')
next_line(c, c_end);
else if (*c == '\t' || *c == '\n' || *c == '\r' || *c == ' ')
@@ -580,14 +595,28 @@ KeyValueConfigFile::KeyValueConfigFile(const Source & s, const Defaults & d,
{
while (*c == '\t' || *c == ' ')
if (++c == c_end)
- throw ConfigFileError(s.filename(), "Unknown command or broken variable '" + key + "' at end of input");
+ throw ConfigFileError(s.filename(), "Unknown command or broken variable '" +
+ key + "' at end of input");
if (*c != '=')
{
if (key == "source")
- throw ConfigFileError(s.filename(), "'source' not yet supported");
+ {
+ std::string value(strip_leading(strip_trailing(
+ grab_value(c, c_end, *this, s.filename()), " \t"), "\t"));
+ if (value.empty())
+ throw ConfigFileError(s.filename(), "source expects a filename");
+ FSEntry target(value);
+ if (! target.exists())
+ throw ConfigFileError(s.filename(), "source argument '" + stringify(target) +
+ "' does not exist");
+ Source ts(target);
+ sources.push_back(std::make_pair(ts, std::istreambuf_iterator<char>(ts.stream())));
+ continue;
+ }
else
- throw ConfigFileError(s.filename(), "Unknown command or broken variable '" + key + "', trailing text '"
+ throw ConfigFileError(s.filename(), "Unknown command or broken variable '" +
+ key + "', trailing text '"
+ std::string(c, c_end) + "'");
}
}
diff --git a/paludis/config_file_TEST.cc b/paludis/config_file_TEST.cc
index 750fd8e..807451e 100644
--- a/paludis/config_file_TEST.cc
+++ b/paludis/config_file_TEST.cc
@@ -251,6 +251,30 @@ namespace test_cases
}
} test_key_value_config_file_defaults;
+ struct KeyValueConfigFileSourceTest : TestCase
+ {
+ KeyValueConfigFileSourceTest() : TestCase("key value config file source") { }
+
+ void run()
+ {
+ std::stringstream d_s;
+ d_s << "six=\"llama\"" << std::endl;
+ d_s << "seven=\"spider\"" << std::endl;
+ d_s << "source config_file_TEST_dir/sourced_one" << std::endl;
+ d_s << "eight=\"octopus\"" << std::endl;
+ KeyValueConfigFile ff(d_s);
+
+ TEST_CHECK_EQUAL(ff.get("one"), "cat");
+ TEST_CHECK_EQUAL(ff.get("two"), "dog");
+ TEST_CHECK_EQUAL(ff.get("three"), "koala");
+ TEST_CHECK_EQUAL(ff.get("four"), "sheep");
+ TEST_CHECK_EQUAL(ff.get("five"), "rabbit");
+ TEST_CHECK_EQUAL(ff.get("six"), "llama");
+ TEST_CHECK_EQUAL(ff.get("seven"), "spider");
+ TEST_CHECK_EQUAL(ff.get("eight"), "octopus");
+ }
+ } test_key_value_config_file_source;
+
/**
* \test Test KeyValueConfigFile errors.
*
diff --git a/paludis/config_file_TEST_setup.sh b/paludis/config_file_TEST_setup.sh
index a35809b..fd0bb10 100755
--- a/paludis/config_file_TEST_setup.sh
+++ b/paludis/config_file_TEST_setup.sh
@@ -7,3 +7,20 @@ echo "I am a fish." > config_file || exit 4
echo "I am a fish too." > unreadable_file || exit 5
chmod a-r unreadable_file || exit 6
+cat <<"END" > sourced_one
+one="cat"
+two="dog"
+three="fish"
+source config_file_TEST_dir/sourced_two
+four="sheep"
+file="config_file_TEST_dir/sourced_two"
+source "${file}"
+two="dog"
+END
+
+cat <<"END" > sourced_two
+two="chimp"
+three="koala"
+five="rabbit"
+END
+