소스 검색

merge from the lp:~donkult/apt/sid branch

Michael Vogt 16 년 전
부모
커밋
113942be71

+ 1 - 1
apt-inst/makefile

@@ -14,7 +14,7 @@ include ../buildlib/libversion.mak
 
 
 # The library name
 # The library name
 LIBRARY=apt-inst
 LIBRARY=apt-inst
-MAJOR=1.1
+MAJOR=1.2
 MINOR=0
 MINOR=0
 SLIBS=$(PTHREADLIB) -lapt-pkg
 SLIBS=$(PTHREADLIB) -lapt-pkg
 APT_DOMAIN:=libapt-inst$(MAJOR)
 APT_DOMAIN:=libapt-inst$(MAJOR)

+ 132 - 38
apt-pkg/aptconfiguration.cc

@@ -8,13 +8,18 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#include <apt-pkg/fileutl.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/macros.h>
+#include <apt-pkg/strutl.h>
+
+#include <sys/types.h>
+#include <dirent.h>
 
 
-#include <vector>
-#include <string>
 #include <algorithm>
 #include <algorithm>
+#include <string>
+#include <vector>
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 // getCompressionTypes - Return Vector of usbale compressiontypes	/*{{{*/
 // getCompressionTypes - Return Vector of usbale compressiontypes	/*{{{*/
@@ -96,7 +101,7 @@ const Configuration::getCompressionTypes(bool const &Cached) {
    will result in "de_DE, de, en".
    will result in "de_DE, de, en".
    The special word "none" is the stopcode for the not-All code vector */
    The special word "none" is the stopcode for the not-All code vector */
 std::vector<std::string> const Configuration::getLanguages(bool const &All,
 std::vector<std::string> const Configuration::getLanguages(bool const &All,
-				bool const &Cached, char const * const Locale) {
+				bool const &Cached, char const ** const Locale) {
 	using std::string;
 	using std::string;
 
 
 	// The detection is boring and has a lot of cornercases,
 	// The detection is boring and has a lot of cornercases,
@@ -117,27 +122,64 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 		}
 		}
 	}
 	}
 
 
-	// get the environment language code
+	// 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);
+		}
+	}
+
+	// get the environment language codes: LC_MESSAGES (and later LANGUAGE)
 	// we extract both, a long and a short code and then we will
 	// 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
 	// check if we actually need both (rare) or if the short is enough
-	string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : Locale);
+	string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale);
 	size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
 	size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
-	size_t const lenLong = (envMsg.find('.') != string::npos) ? envMsg.find('.') : (lenShort + 3);
+	size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3);
 
 
 	string envLong = envMsg.substr(0,lenLong);
 	string envLong = envMsg.substr(0,lenLong);
 	string const envShort = envLong.substr(0,lenShort);
 	string const envShort = envLong.substr(0,lenShort);
-	bool envLongIncluded = true, envShortIncluded = false;
+	bool envLongIncluded = true;
 
 
 	// first cornercase: LANG=C, so we use only "en" Translation
 	// first cornercase: LANG=C, so we use only "en" Translation
 	if (envLong == "C") {
 	if (envLong == "C") {
 		codes.push_back("en");
 		codes.push_back("en");
-		return codes;
+		allCodes = codes;
+		allCodes.insert(allCodes.end(), builtin.begin(), builtin.end());
+		if (All == true)
+			return allCodes;
+		else
+			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
+	char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL };
 	if (envLong != envShort) {
 	if (envLong != envShort) {
-		// 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...
-		char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL };
 		for (char const **l = needLong; *l != NULL; l++)
 		for (char const **l = needLong; *l != NULL; l++)
 			if (envShort.compare(*l) == 0) {
 			if (envShort.compare(*l) == 0) {
 				envLongIncluded = false;
 				envLongIncluded = false;
@@ -155,7 +197,51 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 	if (oldAcquire.empty() == false && oldAcquire != "environment") {
 	if (oldAcquire.empty() == false && oldAcquire != "environment") {
 		if (oldAcquire != "none")
 		if (oldAcquire != "none")
 			codes.push_back(oldAcquire);
 			codes.push_back(oldAcquire);
-		return codes;
+		codes.push_back("en");
+		allCodes = 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)
+					continue;
+			}
+			++addedLangs;
+			environment.push_back(*e);
+		}
 	}
 	}
 
 
 	// Support settings like Acquire::Translation=none on the command line to
 	// Support settings like Acquire::Translation=none on the command line to
@@ -163,26 +249,35 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 	string const forceLang = _config->Find("Acquire::Languages","");
 	string const forceLang = _config->Find("Acquire::Languages","");
 	if (forceLang.empty() == false) {
 	if (forceLang.empty() == false) {
 		if (forceLang == "environment") {
 		if (forceLang == "environment") {
-			if (envLongIncluded == false)
-				codes.push_back(envLong);
-			if (envShortIncluded == false)
-				codes.push_back(envShort);
-			return codes;
+			codes = environment;
 		} else if (forceLang != "none")
 		} else if (forceLang != "none")
 			codes.push_back(forceLang);
 			codes.push_back(forceLang);
-		return codes;
+		allCodes = 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;
 	}
 	}
 
 
 	std::vector<string> const lang = _config->FindVector("Acquire::Languages");
 	std::vector<string> const lang = _config->FindVector("Acquire::Languages");
 	// the default setting -> "environment, en"
 	// the default setting -> "environment, en"
 	if (lang.empty() == true) {
 	if (lang.empty() == true) {
-		if (envLongIncluded == false)
-			codes.push_back(envLong);
-		if (envShortIncluded == false)
-			codes.push_back(envShort);
+		codes = environment;
 		if (envShort != "en")
 		if (envShort != "en")
 			codes.push_back("en");
 			codes.push_back("en");
-		return codes;
+		allCodes = 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
 	// the configs define the order, so add the environment
@@ -191,32 +286,31 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 	for (std::vector<string>::const_iterator l = lang.begin();
 	for (std::vector<string>::const_iterator l = lang.begin();
 	     l != lang.end(); l++) {
 	     l != lang.end(); l++) {
 		if (*l == "environment") {
 		if (*l == "environment") {
-			if (envLongIncluded == true && envShortIncluded == true)
-				continue;
-			if (envLongIncluded == false) {
-				envLongIncluded = true;
-				if (noneSeen == false)
-					codes.push_back(envLong);
-				allCodes.push_back(envLong);
-			}
-			if (envShortIncluded == false) {
-				envShortIncluded = true;
+			for (std::vector<string>::const_iterator e = environment.begin();
+			     e != environment.end(); ++e) {
+				if (std::find(allCodes.begin(), allCodes.end(), *e) != allCodes.end())
+					continue;
 				if (noneSeen == false)
 				if (noneSeen == false)
-					codes.push_back(envShort);
-				allCodes.push_back(envShort);
+					codes.push_back(*e);
+				allCodes.push_back(*e);
 			}
 			}
 			continue;
 			continue;
 		} else if (*l == "none") {
 		} else if (*l == "none") {
 			noneSeen = true;
 			noneSeen = true;
 			continue;
 			continue;
-		} else if ((envLongIncluded == true && *l == envLong) ||
-		         (envShortIncluded == true && *l == envShort))
+		} else if (std::find(allCodes.begin(), allCodes.end(), *l) != allCodes.end())
 			continue;
 			continue;
 
 
 		if (noneSeen == false)
 		if (noneSeen == false)
 			codes.push_back(*l);
 			codes.push_back(*l);
 		allCodes.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)
 	if (All == true)
 		return allCodes;
 		return allCodes;
 	else
 	else

+ 1 - 1
apt-pkg/aptconfiguration.h

@@ -64,7 +64,7 @@ public:									/*{{{*/
 	 *  \return a vector of (all) Language Codes in the prefered usage order
 	 *  \return a vector of (all) Language Codes in the prefered usage order
 	 */
 	 */
 	std::vector<std::string> static const getLanguages(bool const &All = false,
 	std::vector<std::string> static const getLanguages(bool const &All = false,
-			bool const &Cached = true, char const * const Locale = 0);
+			bool const &Cached = true, char const ** const Locale = 0);
 
 
 									/*}}}*/
 									/*}}}*/
 };
 };

+ 18 - 0
apt-pkg/contrib/strutl.cc

@@ -1000,6 +1000,24 @@ bool TokSplitString(char Tok,char *Input,char **List,
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// ExplodeString - Split a string up into a vector			/*{{{*/
+// ---------------------------------------------------------------------
+/* This can be used to split a given string up into a vector, so the
+   propose is the same as in the method above and this one is a bit slower
+   also, but the advantage is that we an iteratable vector */
+vector<string> ExplodeString(string const &haystack, char const &split)
+{
+   string::const_iterator start = haystack.begin();
+   string::const_iterator end = start;
+   vector<string> exploded;
+   do {
+      for (; end != haystack.end() && *end != split; ++end);
+      exploded.push_back(string(start, end));
+      start = end + 1;
+   } while (end != haystack.end() && (++end) != haystack.end());
+   return exploded;
+}
+									/*}}}*/
 // RegexChoice - Simple regex list/list matcher				/*{{{*/
 // RegexChoice - Simple regex list/list matcher				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */

+ 1 - 0
apt-pkg/contrib/strutl.h

@@ -59,6 +59,7 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0)
 bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length);
 bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length);
 bool TokSplitString(char Tok,char *Input,char **List,
 bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);
 		    unsigned long ListMax);
+vector<string> ExplodeString(string const &haystack, char const &split);
 void ioprintf(ostream &out,const char *format,...) APT_FORMAT2;
 void ioprintf(ostream &out,const char *format,...) APT_FORMAT2;
 void strprintf(string &out,const char *format,...) APT_FORMAT2;
 void strprintf(string &out,const char *format,...) APT_FORMAT2;
 char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3;
 char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3;

+ 4 - 1
apt-pkg/deb/debmetaindex.cc

@@ -181,6 +181,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
       for (vector<string>::const_iterator l = lang.begin();
       for (vector<string>::const_iterator l = lang.begin();
 		l != lang.end(); l++)
 		l != lang.end(); l++)
       {
       {
+	if (*l == "none") continue;
 	debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str());
 	debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str());
 	i.GetIndexes(Owner);
 	i.GetIndexes(Owner);
       }
       }
@@ -219,8 +220,10 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
          Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
          Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
 
 
 	 for (vector<string>::const_iterator l = lang.begin();
 	 for (vector<string>::const_iterator l = lang.begin();
-		l != lang.end(); l++)
+		l != lang.end(); l++) {
+	    if (*l == "none") continue;
 	    Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()));
 	    Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()));
+	 }
       }
       }
    }
    }
 
 

+ 1 - 1
apt-pkg/deb/dpkgpm.cc

@@ -1063,7 +1063,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
 
 	 // wait for input or output here
 	 // wait for input or output here
 	 FD_ZERO(&rfds);
 	 FD_ZERO(&rfds);
-	 if (!stdin_is_dev_null)
+	 if (master >= 0 && !stdin_is_dev_null)
 	    FD_SET(0, &rfds); 
 	    FD_SET(0, &rfds); 
 	 FD_SET(_dpkgin, &rfds);
 	 FD_SET(_dpkgin, &rfds);
 	 if(master >= 0)
 	 if(master >= 0)

+ 1 - 1
apt-pkg/init.h

@@ -22,7 +22,7 @@
 // Non-ABI-Breaks should only increase RELEASE number.
 // Non-ABI-Breaks should only increase RELEASE number.
 // See also buildlib/libversion.mak
 // See also buildlib/libversion.mak
 #define APT_PKG_MAJOR 4
 #define APT_PKG_MAJOR 4
-#define APT_PKG_MINOR 8
+#define APT_PKG_MINOR 9
 #define APT_PKG_RELEASE 0
 #define APT_PKG_RELEASE 0
     
     
 extern const char *pkgVersion;
 extern const char *pkgVersion;

+ 3 - 0
buildlib/apti18n.h.in

@@ -11,8 +11,10 @@
 # include <libintl.h>
 # include <libintl.h>
 # ifdef APT_DOMAIN
 # ifdef APT_DOMAIN
 #   define _(x) dgettext(APT_DOMAIN,x)
 #   define _(x) dgettext(APT_DOMAIN,x)
+#   define P_(msg,plural,n) dngettext(APT_DOMAIN,msg,plural,n)
 # else
 # else
 #   define _(x) gettext(x)
 #   define _(x) gettext(x)
+#   define P_(msg,plural,n) ngettext(msg,plural,n)
 # endif
 # endif
 # define N_(x) x
 # define N_(x) x
 #else
 #else
@@ -21,5 +23,6 @@
 # define textdomain(a)
 # define textdomain(a)
 # define bindtextdomain(a, b)
 # define bindtextdomain(a, b)
 # define _(x) x
 # define _(x) x
+# define P_(msg,plural,n) (n == 1 ? msg : plural)
 # define N_(x) x
 # define N_(x) x
 #endif
 #endif

+ 7 - 7
buildlib/library.mak

@@ -16,11 +16,11 @@
 # See defaults.mak for information about LOCAL
 # See defaults.mak for information about LOCAL
 
 
 # Some local definitions
 # Some local definitions
-LOCAL := lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR)
+LOCAL := lib$(LIBRARY).so.$(MAJOR).$(MINOR)
 $(LOCAL)-OBJS := $(addprefix $(OBJ)/,$(addsuffix .opic,$(notdir $(basename $(SOURCE)))))
 $(LOCAL)-OBJS := $(addprefix $(OBJ)/,$(addsuffix .opic,$(notdir $(basename $(SOURCE)))))
 $(LOCAL)-DEP := $(addprefix $(DEP)/,$(addsuffix .opic.d,$(notdir $(basename $(SOURCE)))))
 $(LOCAL)-DEP := $(addprefix $(DEP)/,$(addsuffix .opic.d,$(notdir $(basename $(SOURCE)))))
 $(LOCAL)-HEADERS := $(addprefix $(INCLUDE)/,$(HEADERS))
 $(LOCAL)-HEADERS := $(addprefix $(INCLUDE)/,$(HEADERS))
-$(LOCAL)-SONAME := lib$(LIBRARY)$(LIBEXT).so.$(MAJOR)
+$(LOCAL)-SONAME := lib$(LIBRARY).so.$(MAJOR)
 $(LOCAL)-SLIBS := $(SLIBS)
 $(LOCAL)-SLIBS := $(SLIBS)
 $(LOCAL)-LIBRARY := $(LIBRARY)
 $(LOCAL)-LIBRARY := $(LIBRARY)
 
 
@@ -29,7 +29,7 @@ include $(PODOMAIN_H)
 
 
 # Install the command hooks
 # Install the command hooks
 headers: $($(LOCAL)-HEADERS)
 headers: $($(LOCAL)-HEADERS)
-library: $(LIB)/lib$(LIBRARY).so $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR)
+library: $(LIB)/lib$(LIBRARY).so $(LIB)/lib$(LIBRARY).so.$(MAJOR)
 clean: clean/$(LOCAL)
 clean: clean/$(LOCAL)
 veryclean: veryclean/$(LOCAL)
 veryclean: veryclean/$(LOCAL)
 
 
@@ -44,14 +44,14 @@ veryclean/$(LOCAL): clean/$(LOCAL)
 	-rm -f $($(@F)-HEADERS) $(LIB)/lib$($(@F)-LIBRARY)*.so*
 	-rm -f $($(@F)-HEADERS) $(LIB)/lib$($(@F)-LIBRARY)*.so*
 
 
 # Build rules for the two symlinks
 # Build rules for the two symlinks
-.PHONY: $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR) $(LIB)/lib$(LIBRARY).so
-$(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR): $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR)
+.PHONY: $(LIB)/lib$(LIBRARY).so.$(MAJOR) $(LIB)/lib$(LIBRARY).so
+$(LIB)/lib$(LIBRARY).so.$(MAJOR): $(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR)
 	ln -sf $(<F) $@
 	ln -sf $(<F) $@
-$(LIB)/lib$(LIBRARY).so: $(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR)
+$(LIB)/lib$(LIBRARY).so: $(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR)
 	ln -sf $(<F) $@
 	ln -sf $(<F) $@
 
 
 # The binary build rule
 # The binary build rule
-$(LIB)/lib$(LIBRARY)$(LIBEXT).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS)
+$(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS)
 	-rm -f $(LIB)/lib$($(@F)-LIBRARY)*.so* 2> /dev/null
 	-rm -f $(LIB)/lib$($(@F)-LIBRARY)*.so* 2> /dev/null
 	echo Building shared library $@
 	echo Building shared library $@
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(PICFLAGS) $(LFLAGS) $(LFLAGS_SO)\
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(PICFLAGS) $(LFLAGS) $(LFLAGS_SO)\

+ 0 - 7
buildlib/libversion.mak

@@ -12,10 +12,3 @@ LIBAPTPKG_RELEASE=$(shell grep -E '^\#define APT_PKG_RELEASE' $(BASE)/apt-pkg/in
 # The versionnumber is extracted from apt-inst/makefile - see also there.
 # The versionnumber is extracted from apt-inst/makefile - see also there.
 LIBAPTINST_MAJOR=$(shell egrep '^MAJOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
 LIBAPTINST_MAJOR=$(shell egrep '^MAJOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
 LIBAPTINST_MINOR=$(shell egrep '^MINOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
 LIBAPTINST_MINOR=$(shell egrep '^MINOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
-
-# FIXME: In previous releases this lovely variable includes
-# the detected libc and libdc++ version. As this is bogus we
-# want to drop this, but this a ABI break.
-# And we don't want to do this now. So we hardcode a value here,
-# and drop it later on (hopefully as fast as possible).
-LIBEXT=-libc6.9-6

+ 7 - 5
cmdline/apt-get.cc

@@ -1504,10 +1504,9 @@ bool DoAutomaticRemove(CacheFile &Cache)
 	    // only show stuff in the list that is not yet marked for removal
 	    // only show stuff in the list that is not yet marked for removal
 	    if(Cache[Pkg].Delete() == false) 
 	    if(Cache[Pkg].Delete() == false) 
 	    {
 	    {
+	       ++autoRemoveCount;
 	       // we don't need to fill the strings if we don't need them
 	       // we don't need to fill the strings if we don't need them
-	       if (smallList == true)
-		  ++autoRemoveCount;
-	       else
+	       if (smallList == false)
 	       {
 	       {
 		 autoremovelist += string(Pkg.Name()) + " ";
 		 autoremovelist += string(Pkg.Name()) + " ";
 		 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
 		 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
@@ -1520,9 +1519,12 @@ bool DoAutomaticRemove(CacheFile &Cache)
    if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
    if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
    {
    {
       if (smallList == false)
       if (smallList == false)
-	 ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
+	 ShowList(c1out, P_("The following package is automatically installed and is no longer required:",
+	          "The following packages were automatically installed and are no longer required:",
+	          autoRemoveCount), autoremovelist, autoremoveversions);
       else
       else
-	 ioprintf(c1out, _("%lu packages were automatically installed and are no longer required.\n"), autoRemoveCount);
+	 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
+	          "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
       c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
       c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
    }
    }
    // Now see if we had destroyed anything (if we had done anything)
    // Now see if we had destroyed anything (if we had done anything)

+ 18 - 0
debian/changelog

@@ -15,9 +15,27 @@ apt (0.7.26) UNRELEASED; urgency=low
     - allow also to skip the last patch if target is reached,
     - allow also to skip the last patch if target is reached,
       thanks Bernhard R. Link! (Closes: #545699)
       thanks Bernhard R. Link! (Closes: #545699)
   * ftparchive/writer.{cc,h}:
   * ftparchive/writer.{cc,h}:
+    - add --arch option for packages and contents commands
+    - if an arch is given accept only *_all.deb and *_arch.deb instead
+      of *.deb. Thanks Stephan Bosch for the patch! (Closes: #319710)
     - add APT::FTPArchive::AlwaysStat to disable the too aggressive
     - add APT::FTPArchive::AlwaysStat to disable the too aggressive
       caching if versions are build multiply times (not recommend)
       caching if versions are build multiply times (not recommend)
       Patch by Christoph Goehre, thanks! (Closes: #463260)
       Patch by Christoph Goehre, thanks! (Closes: #463260)
+  * apt-pkg/deb/dpkgpm.cc:
+    - stdin redirected to /dev/null takes all CPU (Closes: #569488)
+      Thanks to Aurelien Jarno for providing (again) a patch!
+  * buildlib/apti18n.h.in, po/makefile:
+    - add ngettext support with P_()
+  * aptconfiguration.cc:
+    - include all existing Translation files in the Cache (Closes: 564137)
+  * debian/control:
+    - update with no changes to debian policy 3.8.4
+  * doc/apt_preferences.5.xml:
+    - explicitly warn against careless use (Closes: #567669)
+  * debian/rules:
+    - remove creation of empty dir /usr/share/apt
+  * doc/apt-cdrom.8.xml:
+    - fix typo spotted by lintian: proc(c)eed
 
 
   [ Ivan Masár ]
   [ Ivan Masár ]
   * Slovak translation update. Closes: #568294
   * Slovak translation update. Closes: #568294

+ 1 - 1
debian/control

@@ -5,7 +5,7 @@ Maintainer: APT Development Team <deity@lists.debian.org>
 Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
 Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
-Standards-Version: 3.8.3
+Standards-Version: 3.8.4
 Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev
 Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev
 Vcs-Bzr: http://bzr.debian.org/apt/debian-sid/
 Vcs-Bzr: http://bzr.debian.org/apt/debian-sid/
 
 

+ 8 - 8
debian/rules

@@ -78,21 +78,21 @@ APT_UTILS=ftparchive sortpkgs extracttemplates
 include buildlib/libversion.mak
 include buildlib/libversion.mak
 
 
 # Determine which package we should provide in the control files
 # Determine which package we should provide in the control files
-LIBAPTPKG_PROVIDE=libapt-pkg$(LIBEXT)-$(LIBAPTPKG_MAJOR)
-LIBAPTINST_PROVIDE=libapt-inst$(LIBEXT)-$(LIBAPTINST_MAJOR)
+LIBAPTPKG_PROVIDE=libapt-pkg-$(LIBAPTPKG_MAJOR)
+LIBAPTINST_PROVIDE=libapt-inst-$(LIBAPTINST_MAJOR)
 
 
 debian/shlibs.local: apt-pkg/makefile
 debian/shlibs.local: apt-pkg/makefile
 	# We have 3 shlibs.local files.. One for 'apt', one for 'apt-utils' and
 	# We have 3 shlibs.local files.. One for 'apt', one for 'apt-utils' and
 	# one for the rest of the packages. This ensures that each package gets
 	# one for the rest of the packages. This ensures that each package gets
 	# the right overrides.. 
 	# the right overrides.. 
 	rm -rf $@ $@.apt $@.apt-utils
 	rm -rf $@ $@.apt $@.apt-utils
-	echo "libapt-pkg$(LIBEXT) $(LIBAPTPKG_MAJOR)" > $@.apt
+	echo "libapt-pkg $(LIBAPTPKG_MAJOR)" > $@.apt
 
 
-	echo "libapt-pkg$(LIBEXT) $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@.apt-utils
-	echo "libapt-inst$(LIBEXT) $(LIBAPTINST_MAJOR)" >> $@.apt-utils
+	echo "libapt-pkg $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@.apt-utils
+	echo "libapt-inst $(LIBAPTINST_MAJOR)" >> $@.apt-utils
 
 
-	echo "libapt-pkg$(LIBEXT) $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@
-	echo "libapt-inst$(LIBEXT) $(LIBAPTINST_MAJOR) $(LIBAPTINST_PROVIDE)" >> $@
+	echo "libapt-pkg $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@
+	echo "libapt-inst $(LIBAPTINST_MAJOR) $(LIBAPTINST_PROVIDE)" >> $@
 
 
 build: build/build-stamp	
 build: build/build-stamp	
 build-doc: build/build-doc-stamp	
 build-doc: build/build-doc-stamp	
@@ -190,7 +190,7 @@ apt: build build-doc debian/shlibs.local
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_clean -p$@ -k
 	dh_clean -p$@ -k
-	dh_installdirs -p$@ /usr/share/bug/$@ /usr/share/$@
+	dh_installdirs -p$@
 #
 #
 # apt install
 # apt install
 #
 #

+ 1 - 1
doc/apt-cdrom.8.xml

@@ -65,7 +65,7 @@
      <varlistentry><term>add</term>
      <varlistentry><term>add</term>
      <listitem><para><literal>add</literal> is used to add a new disc to the
      <listitem><para><literal>add</literal> is used to add a new disc to the
      source list. It will unmount the
      source list. It will unmount the
-     CDROM device, prompt for a disk to be inserted and then procceed to 
+     CDROM device, prompt for a disk to be inserted and then proceed to 
      scan it and copy the index files. If the disc does not have a proper
      scan it and copy the index files. If the disc does not have a proper
      <filename>disk</filename> directory you will be prompted for a descriptive 
      <filename>disk</filename> directory you will be prompted for a descriptive 
      title.
      title.

+ 10 - 2
doc/apt-ftparchive.1.xml

@@ -39,6 +39,7 @@
       <arg><option>--delink</option></arg>
       <arg><option>--delink</option></arg>
       <arg><option>--readonly</option></arg>
       <arg><option>--readonly</option></arg>
       <arg><option>--contents</option></arg>
       <arg><option>--contents</option></arg>
+      <arg><option>--arch <replaceable>architecture</replaceable></option></arg>
       <arg><option>-o <replaceable>config</replaceable>=<replaceable>string</replaceable></option></arg>
       <arg><option>-o <replaceable>config</replaceable>=<replaceable>string</replaceable></option></arg>
       <arg><option>-c=<replaceable>file</replaceable></option></arg>      
       <arg><option>-c=<replaceable>file</replaceable></option></arg>      
       <group choice="req">
       <group choice="req">
@@ -542,11 +543,18 @@ for i in Sections do
      <listitem><para>
      <listitem><para>
      Make the caching databases read only. 
      Make the caching databases read only. 
      Configuration Item: <literal>APT::FTPArchive::ReadOnlyDB</literal>.</para></listitem>
      Configuration Item: <literal>APT::FTPArchive::ReadOnlyDB</literal>.</para></listitem>
-     </varlistentry>   
+     </varlistentry>
+
+     <varlistentry><term><option>-a</option></term><term><option>--arch</option></term>
+     <listitem><para>Accept in the <literal>packages</literal> and <literal>contents</literal>
+     commands only package files matching <literal>*_arch.deb</literal> or
+     <literal>*_all.deb</literal> instead of all package files in the given path.
+     Configuration Item: <literal>APT::FTPArchive::Architecture</literal>.</para></listitem>
+     </varlistentry>
 
 
      <varlistentry><term><option>APT::FTPArchive::AlwaysStat</option></term>
      <varlistentry><term><option>APT::FTPArchive::AlwaysStat</option></term>
      <listitem><para>
      <listitem><para>
-     &apt-ftparchive; caches as much as possible of metadata in it is cachedb. If packages
+     &apt-ftparchive; caches as much as possible of metadata in a cachedb. If packages
      are recompiled and/or republished with the same version again, this will lead to problems
      are recompiled and/or republished with the same version again, this will lead to problems
      as the now outdated cached metadata like size and checksums will be used. With this option
      as the now outdated cached metadata like size and checksums will be used. With this option
      enabled this will no longer happen as it will be checked if the file was changed.
      enabled this will no longer happen as it will be checked if the file was changed.

+ 9 - 1
doc/apt_preferences.5.xml

@@ -14,7 +14,7 @@
    &apt-email;
    &apt-email;
    &apt-product;
    &apt-product;
    <!-- The last update date -->
    <!-- The last update date -->
-   <date>04 May 2009</date>
+   <date>16 February 2010</date>
  </refentryinfo>
  </refentryinfo>
 
 
  <refmeta>
  <refmeta>
@@ -53,6 +53,14 @@ earliest in the &sources-list; file.
 The APT preferences file does not affect the choice of instance, only
 The APT preferences file does not affect the choice of instance, only
 the choice of version.</para>
 the choice of version.</para>
 
 
+<para>Preferences are a strong power in the hands of a system administrator
+but they can become also their biggest nightmare if used without care!
+APT will not questioning the preferences so wrong settings will therefore
+lead to uninstallable packages or wrong decisions while upgrading packages.
+Even more problems will arise if multiply distribution releases are mixed
+without a good understanding of the following paragraphs.
+You have been warned.</para>
+
 <para>Note that the files in the <filename>/etc/apt/preferences.d</filename>
 <para>Note that the files in the <filename>/etc/apt/preferences.d</filename>
 directory are parsed in alphanumeric ascending order and need to obey the
 directory are parsed in alphanumeric ascending order and need to obey the
 following naming convention: The files have no or "<literal>pref</literal>"
 following naming convention: The files have no or "<literal>pref</literal>"

+ 4 - 3
ftparchive/apt-ftparchive.cc

@@ -333,7 +333,7 @@ bool PackageMap::GenContents(Configuration &Setup,
    gettimeofday(&StartTime,0);   
    gettimeofday(&StartTime,0);   
    
    
    // Create a package writer object.
    // Create a package writer object.
-   ContentsWriter Contents("");
+   ContentsWriter Contents("", Arch);
    if (PkgExt.empty() == false && Contents.SetExts(PkgExt) == false)
    if (PkgExt.empty() == false && Contents.SetExts(PkgExt) == false)
       return _error->Error(_("Package extension list is too long"));
       return _error->Error(_("Package extension list is too long"));
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
@@ -606,7 +606,7 @@ bool SimpleGenPackages(CommandLine &CmdL)
    
    
    // Create a package writer object.
    // Create a package writer object.
    PackagesWriter Packages(_config->Find("APT::FTPArchive::DB"),
    PackagesWriter Packages(_config->Find("APT::FTPArchive::DB"),
-			   Override, "");   
+			   Override, "", _config->Find("APT::FTPArchive::Architecture"));
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;
    
    
@@ -629,7 +629,7 @@ bool SimpleGenContents(CommandLine &CmdL)
       return ShowHelp(CmdL);
       return ShowHelp(CmdL);
    
    
    // Create a package writer object.
    // Create a package writer object.
-   ContentsWriter Contents(_config->Find("APT::FTPArchive::DB"));
+   ContentsWriter Contents(_config->Find("APT::FTPArchive::DB"), _config->Find("APT::FTPArchive::Architecture"));
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;
    
    
@@ -910,6 +910,7 @@ int main(int argc, const char *argv[])
       {0,"delink","APT::FTPArchive::DeLinkAct",0},
       {0,"delink","APT::FTPArchive::DeLinkAct",0},
       {0,"readonly","APT::FTPArchive::ReadOnlyDB",0},
       {0,"readonly","APT::FTPArchive::ReadOnlyDB",0},
       {0,"contents","APT::FTPArchive::Contents",0},
       {0,"contents","APT::FTPArchive::Contents",0},
+      {'a',"arch","APT::FTPArchive::Architecture",CommandLine::HasArg},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};
       {0,0,0,0}};

+ 14 - 16
ftparchive/writer.cc

@@ -54,7 +54,7 @@ inline void SetTFRewriteData(struct TFRewriteData &tfrd,
 // FTWScanner::FTWScanner - Constructor					/*{{{*/
 // FTWScanner::FTWScanner - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-FTWScanner::FTWScanner()
+FTWScanner::FTWScanner(string const &Arch): Arch(Arch)
 {
 {
    ErrorPrinted = false;
    ErrorPrinted = false;
    NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
    NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
@@ -299,12 +299,11 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string const &ExtOverrides,
 PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string const &ExtOverrides,
-			       string const &aArch) :
-   Db(DB),Stats(Db.Stats), Arch(aArch)
+			       string const &Arch) :
+   FTWScanner(Arch), Db(DB), Stats(Db.Stats)
 {
 {
    Output = stdout;
    Output = stdout;
-   SetExts(".deb .udeb .foo .bar .baz");
-   AddPattern("*.deb");
+   SetExts(".deb .udeb");
    DeLinkLimit = 0;
    DeLinkLimit = 0;
    
    
    // Process the command line options
    // Process the command line options
@@ -340,17 +339,16 @@ bool FTWScanner::SetExts(string const &Vals)
    string::size_type Start = 0;
    string::size_type Start = 0;
    while (Start <= Vals.length()-1)
    while (Start <= Vals.length()-1)
    {
    {
-      string::size_type Space = Vals.find(' ',Start);
-      string::size_type Length;
-      if (Space == string::npos)
+      string::size_type const Space = Vals.find(' ',Start);
+      string::size_type const Length = ((Space == string::npos) ? Vals.length() : Space) - Start;
+      if ( Arch.empty() == false )
       {
       {
-         Length = Vals.length()-Start;
+	 AddPattern(string("*_") + Arch + Vals.substr(Start, Length));
+	 AddPattern(string("*_all") + Vals.substr(Start, Length));
       }
       }
       else
       else
-      {
-         Length = Space-Start;
-      }
-      AddPattern(string("*") + Vals.substr(Start, Length));
+	 AddPattern(string("*") + Vals.substr(Start, Length));
+
       Start += Length + 1;
       Start += Length + 1;
    }
    }
 
 
@@ -767,11 +765,11 @@ bool SourcesWriter::DoPackage(string FileName)
 // ContentsWriter::ContentsWriter - Constructor				/*{{{*/
 // ContentsWriter::ContentsWriter - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-ContentsWriter::ContentsWriter(string const &DB) : 
-		    Db(DB), Stats(Db.Stats)
+ContentsWriter::ContentsWriter(string const &DB, string const &Arch) :
+		    FTWScanner(Arch), Db(DB), Stats(Db.Stats)
 
 
 {
 {
-   AddPattern("*.deb");
+   SetExts(".deb");
    Output = stdout;
    Output = stdout;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 3 - 3
ftparchive/writer.h

@@ -34,6 +34,7 @@ class FTWScanner
 {
 {
    protected:
    protected:
    vector<string> Patterns;
    vector<string> Patterns;
+   string Arch;
    const char *OriginalPath;
    const char *OriginalPath;
    bool ErrorPrinted;
    bool ErrorPrinted;
    
    
@@ -68,7 +69,7 @@ class FTWScanner
    void AddPattern(string const &Pattern) { Patterns.push_back(Pattern); };
    void AddPattern(string const &Pattern) { Patterns.push_back(Pattern); };
    bool SetExts(string const &Vals);
    bool SetExts(string const &Vals);
       
       
-   FTWScanner();
+   FTWScanner(string const &Arch = string());
 };
 };
 
 
 class PackagesWriter : public FTWScanner
 class PackagesWriter : public FTWScanner
@@ -92,7 +93,6 @@ class PackagesWriter : public FTWScanner
    string DirStrip;
    string DirStrip;
    FILE *Output;
    FILE *Output;
    struct CacheDB::Stats &Stats;
    struct CacheDB::Stats &Stats;
-   string Arch;
 
 
    inline bool ReadOverride(string const &File) {return Over.ReadOverride(File);};
    inline bool ReadOverride(string const &File) {return Over.ReadOverride(File);};
    inline bool ReadExtraOverride(string const &File) 
    inline bool ReadExtraOverride(string const &File) 
@@ -125,7 +125,7 @@ class ContentsWriter : public FTWScanner
    void Finish() {Gen.Print(Output);};
    void Finish() {Gen.Print(Output);};
    inline bool ReadyDB(string const &DB) {return Db.ReadyDB(DB);};
    inline bool ReadyDB(string const &DB) {return Db.ReadyDB(DB);};
    
    
-   ContentsWriter(string const &DB);
+   ContentsWriter(string const &DB, string const &Arch = string());
    virtual ~ContentsWriter() {};
    virtual ~ContentsWriter() {};
 };
 };
 
 

+ 1 - 0
po/makefile

@@ -37,6 +37,7 @@ $(POTFILES) : $(PO)/%.pot :
 	cat $(PO)/domains/$*/*.srclist > $(PO)/POTFILES_$*.in
 	cat $(PO)/domains/$*/*.srclist > $(PO)/POTFILES_$*.in
 	$(XGETTEXT) --default-domain=$* --directory=$(BASE) \
 	$(XGETTEXT) --default-domain=$* --directory=$(BASE) \
 	  --add-comments --foreign --keyword=_ --keyword=N_ \
 	  --add-comments --foreign --keyword=_ --keyword=N_ \
+	  --keyword=P_:1,2 \
 	  --files-from=$(PO)/POTFILES_$*.in -o $(PO)/domains/$*/c.pot
 	  --files-from=$(PO)/POTFILES_$*.in -o $(PO)/domains/$*/c.pot
 	rm -f $(PO)/POTFILES_$*.in
 	rm -f $(PO)/POTFILES_$*.in
 	$(MSGCOMM) --more-than=0 $(PO)/domains/$*/c.pot $(PO)/domains/$*/sh.pot --output=$@
 	$(MSGCOMM) --more-than=0 $(PO)/domains/$*/c.pot $(PO)/domains/$*/sh.pot --output=$@

+ 67 - 16
test/libapt/getlanguages_test.cc

@@ -16,76 +16,127 @@ void dumpVector(std::vector<std::string> vec) {
 
 
 int main(int argc,char *argv[])
 int main(int argc,char *argv[])
 {
 {
-	std::vector<std::string> vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+	if (argc != 2) {
+		std::cout << "One parameter expected - given " << argc << std::endl;
+		return 100;
+	}
+
+	char const* env[2];
+	env[0] = "de_DE.UTF-8";
+	env[1] = "";
+
+	std::vector<std::string> vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 2);
 	equals(vec.size(), 2);
 	equals(vec[0], "de");
 	equals(vec[0], "de");
 	equals(vec[1], "en");
 	equals(vec[1], "en");
 
 
 	// Special: Check if the cache is actually in use
 	// Special: Check if the cache is actually in use
-		vec = APT::Configuration::getLanguages(false, true, "en_GB.UTF-8");
+		env[0] = "en_GB.UTF-8";
+		vec = APT::Configuration::getLanguages(false, true, env);
 		equals(vec.size(), 2);
 		equals(vec.size(), 2);
 		equals(vec[0], "de");
 		equals(vec[0], "de");
 		equals(vec[1], "en");
 		equals(vec[1], "en");
 
 
-	vec = APT::Configuration::getLanguages(false, false, "en_GB.UTF-8");
+	env[0] = "en_GB.UTF-8";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 2);
 	equals(vec.size(), 2);
 	equals(vec[0], "en_GB");
 	equals(vec[0], "en_GB");
 	equals(vec[1], "en");
 	equals(vec[1], "en");
 
 
-	vec = APT::Configuration::getLanguages(false, false, "pt_PR.UTF-8");
+	env[0] = "tr_DE@euro";
+	vec = APT::Configuration::getLanguages(false, false, env);
+	equals(vec.size(), 2);
+	equals(vec[0], "tr");
+	equals(vec[1], "en");
+
+	env[0] = "de_NO";
+	env[1] = "se_NO:en_GB:nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en";
+	vec = APT::Configuration::getLanguages(false, false, env);
+	equals(vec.size(), 5);
+	equals(vec[0], "de");
+	equals(vec[1], "en_GB");
+	equals(vec[2], "nb");
+	equals(vec[3], "no");
+	equals(vec[4], "en");
+
+	env[0] = "pt_PR.UTF-8";
+	env[1] = "";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 3);
 	equals(vec.size(), 3);
 	equals(vec[0], "pt_PR");
 	equals(vec[0], "pt_PR");
 	equals(vec[1], "pt");
 	equals(vec[1], "pt");
 	equals(vec[2], "en");
 	equals(vec[2], "en");
 
 
-	vec = APT::Configuration::getLanguages(false, false, "ast_DE.UTF-8"); // bogus, but syntactical correct
+	env[0] = "ast_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(false, false, env); // bogus, but syntactical correct
 	equals(vec.size(), 2);
 	equals(vec.size(), 2);
 	equals(vec[0], "ast");
 	equals(vec[0], "ast");
 	equals(vec[1], "en");
 	equals(vec[1], "en");
 
 
-	vec = APT::Configuration::getLanguages(false, false, "C");
+	env[0] = "C";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 1);
 	equals(vec.size(), 1);
 	equals(vec[0], "en");
 	equals(vec[0], "en");
 
 
 	_config->Set("Acquire::Languages::1", "environment");
 	_config->Set("Acquire::Languages::1", "environment");
 	_config->Set("Acquire::Languages::2", "en");
 	_config->Set("Acquire::Languages::2", "en");
-	vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+	env[0] = "de_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 2);
 	equals(vec.size(), 2);
 	equals(vec[0], "de");
 	equals(vec[0], "de");
 	equals(vec[1], "en");
 	equals(vec[1], "en");
 
 
 	_config->Set("Acquire::Languages::3", "de");
 	_config->Set("Acquire::Languages::3", "de");
-	vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+	env[0] = "de_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 2);
 	equals(vec.size(), 2);
 	equals(vec[0], "de");
 	equals(vec[0], "de");
 	equals(vec[1], "en");
 	equals(vec[1], "en");
 
 
+	_config->Set("Dir::State::lists", argv[1]);
+	vec = APT::Configuration::getLanguages(true, false, env);
+	equals(vec.size(), 5);
+	equals(vec[0], "de");
+	equals(vec[1], "en");
+	equals(vec[2], "none");
+	equals(vec[3], "pt");
+	equals(vec[4], "tr");
+
+	_config->Set("Dir::State::lists", "/non-existing-dir");
 	_config->Set("Acquire::Languages::1", "none");
 	_config->Set("Acquire::Languages::1", "none");
-	vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+	env[0] = "de_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 0);
 	equals(vec.size(), 0);
-	vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
+	env[0] = "de_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(true, false, env);
 	equals(vec[0], "en");
 	equals(vec[0], "en");
 	equals(vec[1], "de");
 	equals(vec[1], "de");
 
 
 	_config->Set("Acquire::Languages::1", "fr");
 	_config->Set("Acquire::Languages::1", "fr");
 	_config->Set("Acquire::Languages", "de_DE");
 	_config->Set("Acquire::Languages", "de_DE");
-	vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8");
+	env[0] = "de_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(false, false, env);
 	equals(vec.size(), 1);
 	equals(vec.size(), 1);
 	equals(vec[0], "de_DE");
 	equals(vec[0], "de_DE");
 
 
 	_config->Set("Acquire::Languages", "none");
 	_config->Set("Acquire::Languages", "none");
-	vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
+	env[0] = "de_DE.UTF-8";
+	vec = APT::Configuration::getLanguages(true, false, env);
 	equals(vec.size(), 0);
 	equals(vec.size(), 0);
 
 
 	_config->Set("Acquire::Languages", "");
 	_config->Set("Acquire::Languages", "");
 	//FIXME: Remove support for this deprecated setting
 	//FIXME: Remove support for this deprecated setting
 		_config->Set("APT::Acquire::Translation", "ast_DE");
 		_config->Set("APT::Acquire::Translation", "ast_DE");
-		vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
-		equals(vec.size(), 1);
+		env[0] = "de_DE.UTF-8";
+		vec = APT::Configuration::getLanguages(true, false, env);
+		equals(vec.size(), 2);
 		equals(vec[0], "ast_DE");
 		equals(vec[0], "ast_DE");
+		equals(vec[1], "en");
 		_config->Set("APT::Acquire::Translation", "none");
 		_config->Set("APT::Acquire::Translation", "none");
-		vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8");
-		equals(vec.size(), 0);
+		env[0] = "de_DE.UTF-8";
+		vec = APT::Configuration::getLanguages(true, false, env);
+		equals(vec.size(), 1);
+		equals(vec[0], "en");
 
 
 	return 0;
 	return 0;
 }
 }

+ 7 - 0
test/libapt/run-tests.sh

@@ -39,6 +39,13 @@ do
 			"${tmppath}/01invalíd"
 			"${tmppath}/01invalíd"
 		ln -s "${tmppath}/anormalfile" "${tmppath}/linkedfile.list"
 		ln -s "${tmppath}/anormalfile" "${tmppath}/linkedfile.list"
 		ln -s "${tmppath}/non-existing-file" "${tmppath}/brokenlink.list"
 		ln -s "${tmppath}/non-existing-file" "${tmppath}/brokenlink.list"
+	elif [ $name = "getLanguages${EXT}" ]; then
+		echo "Prepare Testarea for \033[1;35m$name\033[0m ..."
+		tmppath=$(mktemp -d)
+		touch "${tmppath}/ftp.de.debian.org_debian_dists_sid_main_i18n_Translation-tr" \
+			"${tmppath}/ftp.de.debian.org_debian_dists_sid_main_i18n_Translation-pt" \
+			"${tmppath}/ftp.de.debian.org_debian_dists_sid_main_i18n_Translation-se~" \
+			"${tmppath}/ftp.de.debian.org_debian_dists_sid_main_i18n_Translation-st.bak"
 	fi
 	fi
 
 
 	echo -n "Testing with \033[1;35m${name}\033[0m ... "
 	echo -n "Testing with \033[1;35m${name}\033[0m ... "