aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-01-27 09:36:00 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-01-27 09:36:00 +0000
commit571329770d39cabccccb6d2f3858f64066d72e0c (patch)
tree9db99393535e0abfdb57a9aa0a59073806482532
parent047d1917c262224eb6ea8f66010ba5e672db8658 (diff)
downloadpaludis-571329770d39cabccccb6d2f3858f64066d72e0c.tar.gz
paludis-571329770d39cabccccb6d2f3858f64066d72e0c.tar.xz
Use VirtualConstructor rather than hard coding repository formats
-rw-r--r--paludis/default_config.cc30
-rw-r--r--paludis/default_config.hh18
-rw-r--r--paludis/default_environment.cc13
-rw-r--r--paludis/portage_repository.cc27
-rw-r--r--paludis/portage_repository.hh25
-rw-r--r--paludis/repository.cc5
-rw-r--r--paludis/repository.hh26
-rw-r--r--paludis/virtual_constructor.hh29
8 files changed, 124 insertions, 49 deletions
diff --git a/paludis/default_config.cc b/paludis/default_config.cc
index f751a0f..cd1ab1b 100644
--- a/paludis/default_config.cc
+++ b/paludis/default_config.cc
@@ -20,6 +20,7 @@
#include "create_insert_iterator.hh"
#include "default_config.hh"
+#include "destringify.hh"
#include "dir_iterator.hh"
#include "filter_insert_iterator.hh"
#include "fs_entry.hh"
@@ -77,33 +78,16 @@ DefaultConfig::DefaultConfig()
KeyValueConfigFile k(*repo_file);
- if (k.get("location").empty())
- throw DefaultConfigError("Key 'location' empty or not specified in " +
- stringify(*repo_file));
- if (k.get("format").empty())
- throw DefaultConfigError("Key 'format' empty or not specified in " +
- stringify(*repo_file));
- if (k.get("profile").empty())
- throw DefaultConfigError("Key 'profile' empty or not specified in " +
- stringify(*repo_file));
+ std::string format(k.get("format"));
+ if (format.empty())
+ throw DefaultConfigError("Key 'format' not specified or empty");
int importance(0);
if (! k.get("importance").empty())
- {
- std::stringstream s(k.get("importance"));
- s >> importance;
- if (! s.eof())
- throw DefaultConfigError("Key 'importance' should be a number in "
- + stringify(*repo_file));
- }
+ importance = destringify<int>(k.get("importance"));
- _repos.push_back(RepositoryConfigEntry(k.get("location"),
- k.get("profile"),
- (k.get("cache").empty() ?
- FSEntry(k.get("location")) / "metadata" / "cache" :
- FSEntry(k.get("cache"))),
- k.get("format"),
- importance));
+ std::map<std::string, std::string> keys(k.begin(), k.end());
+ _repos.push_back(RepositoryConfigEntry(format, importance, keys));
}
if (_repos.empty())
diff --git a/paludis/default_config.hh b/paludis/default_config.hh
index f513f7d..93e6f89 100644
--- a/paludis/default_config.hh
+++ b/paludis/default_config.hh
@@ -34,6 +34,7 @@
#include <map>
#include <vector>
+#include <string>
namespace paludis
{
@@ -57,11 +58,10 @@ namespace paludis
*/
enum RepositoryConfigEntryKeys
{
- rce_location, ///< Our location, for example on disk
- rce_profile, ///< Our profile's location
- rce_cache, ///< Our cache location
- rce_format, ///< Our format, for example 'portage'
- rce_importance ///< Our importance, higher being more important
+ rce_format, ///< Our format
+ rce_importance, ///< Our importance, higher being more important
+ rce_keys, ///< Our key/value data
+ last_rce ///< Number of entries
};
/**
@@ -70,12 +70,10 @@ namespace paludis
struct RepositoryConfigEntryTag :
SmartRecordTag<comparison_mode::FullComparisonTag,
comparison_method::SmartRecordCompareByKeyTag<rce_importance> >,
- SmartRecordKeys<RepositoryConfigEntryKeys, 5>,
- SmartRecordKey<rce_location, FSEntry>,
- SmartRecordKey<rce_profile, FSEntry>,
- SmartRecordKey<rce_cache, FSEntry>,
+ SmartRecordKeys<RepositoryConfigEntryKeys, last_rce>,
SmartRecordKey<rce_format, std::string>,
- SmartRecordKey<rce_importance, unsigned>
+ SmartRecordKey<rce_importance, unsigned>,
+ SmartRecordKey<rce_keys, std::map<std::string, std::string> >
{
};
diff --git a/paludis/default_environment.cc b/paludis/default_environment.cc
index fd798e0..59df01e 100644
--- a/paludis/default_environment.cc
+++ b/paludis/default_environment.cc
@@ -19,7 +19,7 @@
#include "default_environment.hh"
#include "package_database.hh"
-#include "portage_repository.hh"
+#include "repository.hh"
#include "default_config.hh"
#include "stringify.hh"
#include "match_package.hh"
@@ -36,14 +36,9 @@ DefaultEnvironment::DefaultEnvironment() :
for (DefaultConfig::RepositoryIterator r(DefaultConfig::get_instance()->begin_repositories()),
r_end(DefaultConfig::get_instance()->end_repositories()) ; r != r_end ; ++r)
- {
- /// \todo class factory
- if (r->get<rce_format>() != "portage")
- throw DefaultConfigError("Unknown repository format '" + r->get<rce_format>() + "'");
- Repository::Pointer repo(new PortageRepository(package_database().raw_pointer(),
- r->get<rce_location>(), r->get<rce_profile>(), r->get<rce_cache>()));
- package_database()->add_repository(repo);
- }
+ package_database()->add_repository(
+ RepositoryMaker::get_instance()->find_maker(r->get<rce_format>())(
+ package_database().raw_pointer(), r->get<rce_keys>()));
/// \bug vdb
}
diff --git a/paludis/portage_repository.cc b/paludis/portage_repository.cc
index 5891401..b80c151 100644
--- a/paludis/portage_repository.cc
+++ b/paludis/portage_repository.cc
@@ -767,3 +767,30 @@ PortageRepository::need_virtual_names() const
}
}
+CountedPtr<Repository>
+PortageRepository::make_portage_repository(
+ const PackageDatabase * const db,
+ const std::map<std::string, std::string> & m)
+{
+ std::string location;
+ if (m.end() == m.find("location") || ((location = m.find("location")->second)).empty())
+ throw PortageRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string profile;
+ if (m.end() == m.find("profile") || ((profile = m.find("profile")->second)).empty())
+ throw PortageRepositoryConfigurationError("Key 'profile' not specified or empty");
+
+ std::string cache;
+ if (m.end() == m.find("cache") || ((profile = m.find("cache")->second)).empty())
+ cache = location + "/metadata/cache";
+
+ return CountedPtr<Repository>(new PortageRepository(db, location, profile, cache));
+}
+
+PortageRepositoryConfigurationError::PortageRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("Portage repository configuration error: " + msg)
+{
+}
+
+
diff --git a/paludis/portage_repository.hh b/paludis/portage_repository.hh
index 8face69..ad9043a 100644
--- a/paludis/portage_repository.hh
+++ b/paludis/portage_repository.hh
@@ -23,6 +23,8 @@
#include <paludis/repository.hh>
#include <paludis/fs_entry.hh>
#include <paludis/private_implementation_pattern.hh>
+#include <map>
+#include <string>
/** \file
* Declaration for the PortageRepository class.
@@ -89,10 +91,33 @@ namespace paludis
const FSEntry & cache);
/**
+ * Virtual constructor.
+ */
+ static CountedPtr<Repository> make_portage_repository(
+ const PackageDatabase * const db,
+ const std::map<std::string, std::string> &);
+
+ /**
* Destructor.
*/
~PortageRepository();
};
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * PortageRepository::make_portage_repository.
+ *
+ * \ingroup Exception
+ */
+ class PortageRepositoryConfigurationError : public ConfigurationError
+ {
+ public:
+ PortageRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+
+ static const RepositoryMaker::RegisterMaker register_portage_repository(
+ "portage", &PortageRepository::make_portage_repository);
+
}
#endif
diff --git a/paludis/repository.cc b/paludis/repository.cc
index 9a1462a..3f6cfdd 100644
--- a/paludis/repository.cc
+++ b/paludis/repository.cc
@@ -36,3 +36,8 @@ Repository::name() const
return _name;
}
+NoSuchRepositoryTypeError::NoSuchRepositoryTypeError(const std::string & format) throw ():
+ ConfigurationError("No available maker for repository type '" + format + "'")
+{
+}
+
diff --git a/paludis/repository.hh b/paludis/repository.hh
index 1bfa5a4..18c3973 100644
--- a/paludis/repository.hh
+++ b/paludis/repository.hh
@@ -21,13 +21,16 @@
#define PALUDIS_GUARD_PALUDIS_REPOSITORY_HH 1
#include <paludis/attributes.hh>
-#include <paludis/repository_name.hh>
#include <paludis/category_name_part.hh>
-#include <paludis/package_name_part.hh>
#include <paludis/counted_ptr.hh>
+#include <paludis/exception.hh>
+#include <paludis/package_name_part.hh>
+#include <paludis/repository_name.hh>
+#include <paludis/use_flag_state.hh>
#include <paludis/version_metadata.hh>
#include <paludis/version_spec.hh>
-#include <paludis/use_flag_state.hh>
+#include <paludis/virtual_constructor.hh>
+
#include <map>
#include <string>
@@ -305,6 +308,23 @@ namespace paludis
return do_query_use_mask(u);
}
};
+
+ /**
+ * Thrown if a repository of the specified type does not exist.
+ *
+ * \ingroup Exception
+ */
+ class NoSuchRepositoryTypeError : public ConfigurationError
+ {
+ public:
+ NoSuchRepositoryTypeError(const std::string & format) throw ();
+ };
+
+ class PackageDatabase;
+
+ typedef VirtualConstructor<std::string,
+ CountedPtr<Repository> (*) (const PackageDatabase * const, const std::map<std::string, std::string> &),
+ virtual_constructor_not_found::ThrowException<NoSuchRepositoryTypeError> > RepositoryMaker;
}
#endif
diff --git a/paludis/virtual_constructor.hh b/paludis/virtual_constructor.hh
index 816d9f3..a897abc 100644
--- a/paludis/virtual_constructor.hh
+++ b/paludis/virtual_constructor.hh
@@ -21,9 +21,12 @@
#ifndef PALUDIS_GUARD_PALUDIS_VIRTUAL_CONSTRUCTOR_HH
#define PALUDIS_GUARD_PALUDIS_VIRTUAL_CONSTRUCTOR_HH 1
-#include <vector>
-#include <algorithm>
+#include <paludis/exception.hh>
#include <paludis/instantiation_policy.hh>
+#include <paludis/stringify.hh>
+
+#include <algorithm>
+#include <vector>
/** \file
* Declarations for VirtualConstructor and related classes.
@@ -103,6 +106,23 @@ namespace paludis
}
/**
+ * Thrown if registering a key fails.
+ *
+ * \ingroup Exception
+ * \ingroup VirtualConstructor
+ */
+ class VirtualConstructorRegisterFailure : public Exception
+ {
+ public:
+ template <typename T_>
+ VirtualConstructorRegisterFailure(const T_ & k) throw () :
+ Exception("Virtual constructor registration failed on key '" +
+ stringify(k) + "'")
+ {
+ }
+ };
+
+ /**
* A VirtualConstructor can be used where a mapping between the value of
* some key type (often a string) to the construction of some kind of
* class (possibly via a functor) is required.
@@ -206,9 +226,10 @@ namespace paludis
VirtualConstructor<KeyType_, ValueType_, NotFoundBehaviour_>::register_maker(
const KeyType_ & k, const ValueType_ & v)
{
- entries.insert(std::lower_bound(entries.begin(), entries.end(), k,
+ if (! entries.insert(std::lower_bound(entries.begin(), entries.end(), k,
virtual_constructor_internals::ComparePairByFirst<KeyType_, ValueType_>()),
- std::make_pair(k, v));
+ std::make_pair(k, v))->second)
+ throw VirtualConstructorRegisterFailure(k);
}
}