// Include Files /*{{{*/
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/macros.h>
#include <apt-pkg/strutl.h>
-#include <vector>
-#include <string>
+#include <sys/types.h>
+#include <dirent.h>
+
#include <algorithm>
+#include <string>
+#include <vector>
/*}}}*/
namespace APT {
// getCompressionTypes - Return Vector of usbale compressiontypes /*{{{*/
}
}
+ // Include all Language codes we have a Translation file for in /var/lib/apt/lists
+ // so they will be all included in the Cache.
+ std::vector<string> builtin;
+ DIR *D = opendir(_config->FindDir("Dir::State::lists").c_str());
+ if (D != 0) {
+ builtin.push_back("none");
+ for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) {
+ string const name = Ent->d_name;
+ size_t const foundDash = name.rfind("-");
+ size_t const foundUnderscore = name.rfind("_");
+ if (foundDash == string::npos || foundUnderscore == string::npos ||
+ foundDash <= foundUnderscore ||
+ name.substr(foundUnderscore+1, foundDash-(foundUnderscore+1)) != "Translation")
+ continue;
+ string const c = name.substr(foundDash+1);
+ if (unlikely(c.empty() == true) || c == "en")
+ continue;
+ // Skip unusual files, like backups or that alike
+ string::const_iterator s = c.begin();
+ for (;s != c.end(); ++s) {
+ if (isalpha(*s) == 0)
+ break;
+ }
+ if (s != c.end())
+ continue;
+ if (std::find(builtin.begin(), builtin.end(), c) != builtin.end())
+ continue;
+ builtin.push_back(c);
+ }
+ }
+ closedir(D);
+
// get the environment language codes: LC_MESSAGES (and later LANGUAGE)
// we extract both, a long and a short code and then we will
// check if we actually need both (rare) or if the short is enough
string const envShort = envLong.substr(0,lenShort);
bool envLongIncluded = true;
- // first cornercase: LANG=C, so we use only "en" Translation
- if (envLong == "C") {
- codes.push_back("en");
- allCodes = codes;
- return codes;
- }
-
// to save the servers from unneeded queries, we only try also long codes
// for languages it is realistic to have a long code translation fileā¦
// TODO: Improve translation acquire system to drop them dynamic
// it was undocumented and so it should be not very widthly used
string const oldAcquire = _config->Find("APT::Acquire::Translation","");
if (oldAcquire.empty() == false && oldAcquire != "environment") {
+ // TRANSLATORS: the two %s are APT configuration options
+ _error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
+ "APT::Acquire::Translation", "Acquire::Languages");
if (oldAcquire != "none")
codes.push_back(oldAcquire);
+ codes.push_back("en");
allCodes = codes;
- return codes;
+ for (std::vector<string>::const_iterator b = builtin.begin();
+ b != builtin.end(); ++b)
+ if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
+ allCodes.push_back(*b);
+ if (All == true)
+ return allCodes;
+ else
+ return codes;
}
// It is very likely we will need to environment codes later,
// so let us generate them now from LC_MESSAGES and LANGUAGE
std::vector<string> environment;
- // take care of LC_MESSAGES
- if (envLongIncluded == false)
- environment.push_back(envLong);
- environment.push_back(envShort);
- // take care of LANGUAGE
- string envLang = Locale == 0 ? getenv("LANGUAGE") : *(Locale+1);
- if (envLang.empty() == false) {
- std::vector<string> env = ExplodeString(envLang,':');
- short addedLangs = 0; // add a maximum of 3 fallbacks from the environment
- for (std::vector<string>::const_iterator e = env.begin();
- e != env.end() && addedLangs < 3; ++e) {
- if (unlikely(e->empty() == true) || *e == "en")
- continue;
- if (*e == envLong || *e == envShort)
- continue;
- if (std::find(environment.begin(), environment.end(), *e) != environment.end())
- continue;
- if (e->find('_') != string::npos) {
- // Drop LongCodes here - ShortCodes are also included
- string const shorty = e->substr(0, e->find('_'));
- char const **n = needLong;
- for (; *n != NULL; ++n)
- if (shorty == *n)
- break;
- if (*n == NULL)
+ if (envShort != "C") {
+ // take care of LC_MESSAGES
+ if (envLongIncluded == false)
+ environment.push_back(envLong);
+ environment.push_back(envShort);
+ // take care of LANGUAGE
+ const char *language_env = getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
+ string envLang = Locale == 0 ? language_env : *(Locale+1);
+ if (envLang.empty() == false) {
+ std::vector<string> env = VectorizeString(envLang,':');
+ short addedLangs = 0; // add a maximum of 3 fallbacks from the environment
+ for (std::vector<string>::const_iterator e = env.begin();
+ e != env.end() && addedLangs < 3; ++e) {
+ if (unlikely(e->empty() == true) || *e == "en")
+ continue;
+ if (*e == envLong || *e == envShort)
+ continue;
+ if (std::find(environment.begin(), environment.end(), *e) != environment.end())
continue;
+ if (e->find('_') != string::npos) {
+ // Drop LongCodes here - ShortCodes are also included
+ string const shorty = e->substr(0, e->find('_'));
+ char const **n = needLong;
+ for (; *n != NULL; ++n)
+ if (shorty == *n)
+ break;
+ if (*n == NULL)
+ continue;
+ }
+ ++addedLangs;
+ environment.push_back(*e);
}
- ++addedLangs;
- environment.push_back(*e);
}
+ } else {
+ environment.push_back("en");
}
// Support settings like Acquire::Translation=none on the command line to
} else if (forceLang != "none")
codes.push_back(forceLang);
allCodes = codes;
- return codes;
+ for (std::vector<string>::const_iterator b = builtin.begin();
+ b != builtin.end(); ++b)
+ if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
+ allCodes.push_back(*b);
+ if (All == true)
+ return allCodes;
+ else
+ return codes;
+ }
+
+ // cornercase: LANG=C, so we use only "en" Translation
+ if (envShort == "C") {
+ allCodes = codes = environment;
+ allCodes.insert(allCodes.end(), builtin.begin(), builtin.end());
+ if (All == true)
+ return allCodes;
+ else
+ return codes;
}
std::vector<string> const lang = _config->FindVector("Acquire::Languages");
if (envShort != "en")
codes.push_back("en");
allCodes = codes;
- return codes;
+ for (std::vector<string>::const_iterator b = builtin.begin();
+ b != builtin.end(); ++b)
+ if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
+ allCodes.push_back(*b);
+ if (All == true)
+ return allCodes;
+ else
+ return codes;
}
// the configs define the order, so add the environment
codes.push_back(*l);
allCodes.push_back(*l);
}
+
+ for (std::vector<string>::const_iterator b = builtin.begin();
+ b != builtin.end(); ++b)
+ if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
+ allCodes.push_back(*b);
+
if (All == true)
return allCodes;
else
return codes;
}
/*}}}*/
+// getArchitectures - Return Vector of prefered Architectures /*{{{*/
+std::vector<std::string> const Configuration::getArchitectures(bool const &Cached) {
+ using std::string;
+
+ std::vector<string> static archs;
+ if (likely(Cached == true) && archs.empty() == false)
+ return archs;
+
+ archs = _config->FindVector("APT::Architectures");
+ string const arch = _config->Find("APT::Architecture");
+ if (unlikely(arch.empty() == true))
+ return archs;
+
+ if (archs.empty() == true ||
+ std::find(archs.begin(), archs.end(), arch) == archs.end())
+ archs.push_back(arch);
+
+ // erase duplicates and empty strings
+ for (std::vector<string>::reverse_iterator a = archs.rbegin();
+ a != archs.rend(); ++a) {
+ if (a->empty() == true || std::find(a + 1, archs.rend(), *a) != archs.rend())
+ archs.erase(a.base()-1);
+ if (a == archs.rend())
+ break;
+ }
+
+ return archs;
+}
+ /*}}}*/
+// checkArchitecture - are we interested in the given Architecture? /*{{{*/
+bool const Configuration::checkArchitecture(std::string const &Arch) {
+ if (Arch == "all")
+ return true;
+ std::vector<std::string> const archs = getArchitectures(true);
+ return (std::find(archs.begin(), archs.end(), Arch) != archs.end());
+}
+ /*}}}*/
}