warning: no previous declaration for foobar() [-Wmissing-declarations]
[ntk/apt.git] / apt-pkg / aptconfiguration.cc
CommitLineData
e878aedb
DK
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3/* ######################################################################
4
5 Provide access methods to various configuration settings,
6 setup defaults and returns validate settings.
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
ea542140
DK
11#include <config.h>
12
e878aedb
DK
13#include <apt-pkg/aptconfiguration.h>
14#include <apt-pkg/configuration.h>
9f9717fa 15#include <apt-pkg/error.h>
d7cf5923
DK
16#include <apt-pkg/fileutl.h>
17#include <apt-pkg/macros.h>
18#include <apt-pkg/strutl.h>
e878aedb 19
3f2d77b5
DK
20#include <sys/types.h>
21#include <dirent.h>
8aec002f 22#include <stdio.h>
b9ed63d3 23#include <fcntl.h>
3f2d77b5 24
8bd02d8b 25#include <algorithm>
3f2d77b5
DK
26#include <string>
27#include <vector>
e878aedb
DK
28 /*}}}*/
29namespace APT {
1e3f4083 30// getCompressionTypes - Return Vector of usable compressiontypes /*{{{*/
e878aedb 31// ---------------------------------------------------------------------
1e3f4083 32/* return a vector of compression types in the preferred order. */
e878aedb
DK
33std::vector<std::string>
34const Configuration::getCompressionTypes(bool const &Cached) {
35 static std::vector<std::string> types;
36 if (types.empty() == false) {
37 if (Cached == true)
38 return types;
39 else
40 types.clear();
41 }
42
8bd02d8b
DK
43 // setup the defaults for the compressiontypes => method mapping
44 _config->CndSet("Acquire::CompressionTypes::bz2","bzip2");
b2430e6d 45 _config->CndSet("Acquire::CompressionTypes::xz","xz");
8bd02d8b
DK
46 _config->CndSet("Acquire::CompressionTypes::lzma","lzma");
47 _config->CndSet("Acquire::CompressionTypes::gz","gzip");
48
03bef784 49 setDefaultConfigurationForCompressors();
858fd39f 50 std::vector<APT::Configuration::Compressor> const compressors = getCompressors();
e878aedb 51
8bd02d8b
DK
52 // load the order setting into our vector
53 std::vector<std::string> const order = _config->FindVector("Acquire::CompressionTypes::Order");
54 for (std::vector<std::string>::const_iterator o = order.begin();
f7f0d6c7 55 o != order.end(); ++o) {
8bd02d8b
DK
56 if ((*o).empty() == true)
57 continue;
58 // ignore types we have no method ready to use
79b207bc
DK
59 std::string const method = std::string("Acquire::CompressionTypes::").append(*o);
60 if (_config->Exists(method) == false)
8bd02d8b
DK
61 continue;
62 // ignore types we have no app ready to use
79b207bc 63 std::string const app = _config->Find(method);
858fd39f
DK
64 std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin();
65 for (; c != compressors.end(); ++c)
79b207bc 66 if (c->Name == app)
858fd39f
DK
67 break;
68 if (c == compressors.end())
69 continue;
8bd02d8b 70 types.push_back(*o);
e878aedb
DK
71 }
72
8bd02d8b 73 // move again over the option tree to add all missing compression types
e878aedb
DK
74 ::Configuration::Item const *Types = _config->Tree("Acquire::CompressionTypes");
75 if (Types != 0)
76 Types = Types->Child;
77
78 for (; Types != 0; Types = Types->Next) {
8bd02d8b
DK
79 if (Types->Tag == "Order" || Types->Tag.empty() == true)
80 continue;
81 // ignore types we already have in the vector
82 if (std::find(types.begin(),types.end(),Types->Tag) != types.end())
83 continue;
84 // ignore types we have no app ready to use
858fd39f
DK
85 std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin();
86 for (; c != compressors.end(); ++c)
87 if (c->Name == Types->Value)
88 break;
89 if (c == compressors.end())
90 continue;
e878aedb
DK
91 types.push_back(Types->Tag);
92 }
93
5d885723
DK
94 // add the special "uncompressed" type
95 if (std::find(types.begin(), types.end(), "uncompressed") == types.end())
96 {
8f3ba4e8 97 std::string const uncompr = _config->FindFile("Dir::Bin::uncompressed", "");
5d885723
DK
98 if (uncompr.empty() == true || FileExists(uncompr) == true)
99 types.push_back("uncompressed");
100 }
101
e878aedb
DK
102 return types;
103}
104 /*}}}*/
45df0ad2
DK
105// GetLanguages - Return Vector of Language Codes /*{{{*/
106// ---------------------------------------------------------------------
1e3f4083 107/* return a vector of language codes in the preferred order.
45df0ad2
DK
108 the special word "environment" will be replaced with the long and the short
109 code of the local settings and it will be insured that this will not add
110 duplicates. So in an german local the setting "environment, de_DE, en, de"
111 will result in "de_DE, de, en".
112 The special word "none" is the stopcode for the not-All code vector */
113std::vector<std::string> const Configuration::getLanguages(bool const &All,
d7cf5923 114 bool const &Cached, char const ** const Locale) {
45df0ad2
DK
115 using std::string;
116
117 // The detection is boring and has a lot of cornercases,
118 // so we cache the results to calculated it only once.
119 std::vector<string> static allCodes;
120 std::vector<string> static codes;
121
122 // we have something in the cache
123 if (codes.empty() == false || allCodes.empty() == false) {
124 if (Cached == true) {
125 if(All == true && allCodes.empty() == false)
126 return allCodes;
127 else
128 return codes;
129 } else {
130 allCodes.clear();
131 codes.clear();
132 }
133 }
134
3f2d77b5
DK
135 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
136 // so they will be all included in the Cache.
137 std::vector<string> builtin;
138 DIR *D = opendir(_config->FindDir("Dir::State::lists").c_str());
62d8a765 139 if (D != NULL) {
3f2d77b5
DK
140 builtin.push_back("none");
141 for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) {
527df5a2 142 string const name = SubstVar(Ent->d_name, "%5f", "_");
3f2d77b5 143 size_t const foundDash = name.rfind("-");
7cb28948 144 size_t const foundUnderscore = name.rfind("_", foundDash);
3f2d77b5
DK
145 if (foundDash == string::npos || foundUnderscore == string::npos ||
146 foundDash <= foundUnderscore ||
147 name.substr(foundUnderscore+1, foundDash-(foundUnderscore+1)) != "Translation")
148 continue;
149 string const c = name.substr(foundDash+1);
150 if (unlikely(c.empty() == true) || c == "en")
151 continue;
152 // Skip unusual files, like backups or that alike
153 string::const_iterator s = c.begin();
154 for (;s != c.end(); ++s) {
7cb28948 155 if (isalpha(*s) == 0 && *s != '_')
3f2d77b5
DK
156 break;
157 }
158 if (s != c.end())
159 continue;
160 if (std::find(builtin.begin(), builtin.end(), c) != builtin.end())
161 continue;
162 builtin.push_back(c);
163 }
62d8a765 164 closedir(D);
3f2d77b5
DK
165 }
166
45df0ad2
DK
167 // FIXME: Remove support for the old APT::Acquire::Translation
168 // it was undocumented and so it should be not very widthly used
169 string const oldAcquire = _config->Find("APT::Acquire::Translation","");
170 if (oldAcquire.empty() == false && oldAcquire != "environment") {
9f9717fa
DK
171 // TRANSLATORS: the two %s are APT configuration options
172 _error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
173 "APT::Acquire::Translation", "Acquire::Languages");
45df0ad2
DK
174 if (oldAcquire != "none")
175 codes.push_back(oldAcquire);
3f2d77b5 176 codes.push_back("en");
d7cf5923 177 allCodes = codes;
3f2d77b5
DK
178 for (std::vector<string>::const_iterator b = builtin.begin();
179 b != builtin.end(); ++b)
180 if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
181 allCodes.push_back(*b);
182 if (All == true)
183 return allCodes;
184 else
185 return codes;
45df0ad2
DK
186 }
187
ab53c018
DK
188 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
189 // we extract both, a long and a short code and then we will
190 // check if we actually need both (rare) or if the short is enough
191 string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale);
192 size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
193 size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3);
194
195 string const envLong = envMsg.substr(0,lenLong);
196 string const envShort = envLong.substr(0,lenShort);
197
198 // It is very likely we will need the environment codes later,
d7cf5923
DK
199 // so let us generate them now from LC_MESSAGES and LANGUAGE
200 std::vector<string> environment;
eb3947c6
DK
201 if (envShort != "C") {
202 // take care of LC_MESSAGES
ab53c018 203 if (envLong != envShort)
eb3947c6
DK
204 environment.push_back(envLong);
205 environment.push_back(envShort);
206 // take care of LANGUAGE
207 const char *language_env = getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
208 string envLang = Locale == 0 ? language_env : *(Locale+1);
209 if (envLang.empty() == false) {
210 std::vector<string> env = VectorizeString(envLang,':');
211 short addedLangs = 0; // add a maximum of 3 fallbacks from the environment
212 for (std::vector<string>::const_iterator e = env.begin();
213 e != env.end() && addedLangs < 3; ++e) {
214 if (unlikely(e->empty() == true) || *e == "en")
215 continue;
216 if (*e == envLong || *e == envShort)
217 continue;
218 if (std::find(environment.begin(), environment.end(), *e) != environment.end())
d7cf5923 219 continue;
eb3947c6
DK
220 ++addedLangs;
221 environment.push_back(*e);
d7cf5923 222 }
d7cf5923 223 }
eb3947c6 224 } else {
a5414e56 225 // cornercase: LANG=C, so we use only "en" Translation
eb3947c6 226 environment.push_back("en");
d7cf5923
DK
227 }
228
a5414e56 229 std::vector<string> const lang = _config->FindVector("Acquire::Languages", "environment,en");
45df0ad2
DK
230 // the configs define the order, so add the environment
231 // then needed and ensure the codes are not listed twice.
232 bool noneSeen = false;
233 for (std::vector<string>::const_iterator l = lang.begin();
f7f0d6c7 234 l != lang.end(); ++l) {
45df0ad2 235 if (*l == "environment") {
d7cf5923
DK
236 for (std::vector<string>::const_iterator e = environment.begin();
237 e != environment.end(); ++e) {
238 if (std::find(allCodes.begin(), allCodes.end(), *e) != allCodes.end())
239 continue;
45df0ad2 240 if (noneSeen == false)
d7cf5923
DK
241 codes.push_back(*e);
242 allCodes.push_back(*e);
45df0ad2
DK
243 }
244 continue;
245 } else if (*l == "none") {
246 noneSeen = true;
247 continue;
d7cf5923 248 } else if (std::find(allCodes.begin(), allCodes.end(), *l) != allCodes.end())
45df0ad2
DK
249 continue;
250
251 if (noneSeen == false)
252 codes.push_back(*l);
253 allCodes.push_back(*l);
254 }
3f2d77b5 255
a5414e56
DK
256 if (allCodes.empty() == false) {
257 for (std::vector<string>::const_iterator b = builtin.begin();
258 b != builtin.end(); ++b)
259 if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
260 allCodes.push_back(*b);
261 } else {
262 // "none" was forced
263 allCodes.push_back("none");
264 }
3f2d77b5 265
45df0ad2
DK
266 if (All == true)
267 return allCodes;
268 else
269 return codes;
270}
271 /*}}}*/
c45233ea
DK
272// checkLanguage - are we interested in the given Language? /*{{{*/
273bool const Configuration::checkLanguage(std::string Lang, bool const All) {
274 // the empty Language is always interesting as it is the original
275 if (Lang.empty() == true)
276 return true;
277 // filenames are encoded, so undo this
278 Lang = SubstVar(Lang, "%5f", "_");
279 std::vector<std::string> const langs = getLanguages(All, true);
280 return (std::find(langs.begin(), langs.end(), Lang) != langs.end());
281}
282 /*}}}*/
1e3f4083 283// getArchitectures - Return Vector of preferred Architectures /*{{{*/
5dd4c8b8
DK
284std::vector<std::string> const Configuration::getArchitectures(bool const &Cached) {
285 using std::string;
286
287 std::vector<string> static archs;
288 if (likely(Cached == true) && archs.empty() == false)
289 return archs;
290
3152f4aa 291 string const arch = _config->Find("APT::Architecture");
8aec002f
DK
292 archs = _config->FindVector("APT::Architectures");
293
3152f4aa
DK
294 if (unlikely(arch.empty() == true))
295 return archs;
296
8aec002f
DK
297 // FIXME: It is a bit unclean to have debian specific code here…
298 if (archs.empty() == true) {
299 archs.push_back(arch);
b9ed63d3
DK
300
301 // Generate the base argument list for dpkg
302 std::vector<const char *> Args;
303 string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
304 {
305 string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/");
306 size_t dpkgChrootLen = dpkgChrootDir.length();
307 if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) {
308 if (dpkgChrootDir[dpkgChrootLen - 1] == '/')
309 --dpkgChrootLen;
310 Tmp = Tmp.substr(dpkgChrootLen);
311 }
312 }
313 Args.push_back(Tmp.c_str());
314
315 // Stick in any custom dpkg options
316 ::Configuration::Item const *Opts = _config->Tree("DPkg::Options");
317 if (Opts != 0) {
318 Opts = Opts->Child;
319 for (; Opts != 0; Opts = Opts->Next)
320 {
321 if (Opts->Value.empty() == true)
322 continue;
323 Args.push_back(Opts->Value.c_str());
324 }
325 }
326
327 Args.push_back("--print-foreign-architectures");
328 Args.push_back(NULL);
329
330 int external[2] = {-1, -1};
331 if (pipe(external) != 0)
332 {
333 _error->WarningE("getArchitecture", "Can't create IPC pipe for dpkg --print-foreign-architectures");
334 return archs;
335 }
336
337 pid_t dpkgMultiArch = ExecFork();
338 if (dpkgMultiArch == 0) {
339 close(external[0]);
340 std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
b9ed63d3
DK
341 int const nullfd = open("/dev/null", O_RDONLY);
342 dup2(nullfd, STDIN_FILENO);
343 dup2(external[1], STDOUT_FILENO);
344 dup2(nullfd, STDERR_FILENO);
2510eea4 345 if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0)
36a0c0f7 346 _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str());
17019a09 347 execvp(Args[0], (char**) &Args[0]);
b9ed63d3
DK
348 _error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
349 _exit(100);
350 }
351 close(external[1]);
352
353 FILE *dpkg = fdopen(external[0], "r");
8aec002f 354 if(dpkg != NULL) {
69c2ecbd 355 char buf[1024];
4df62de6 356 while (fgets(buf, sizeof(buf), dpkg) != NULL) {
8aec002f
DK
357 char* arch = strtok(buf, " ");
358 while (arch != NULL) {
359 for (; isspace(*arch) != 0; ++arch);
bdb3d92c 360 if (arch[0] != '\0') {
8aec002f
DK
361 char const* archend = arch;
362 for (; isspace(*archend) == 0 && *archend != '\0'; ++archend);
dd7233af
DK
363 string a(arch, (archend - arch));
364 if (std::find(archs.begin(), archs.end(), a) == archs.end())
365 archs.push_back(a);
8aec002f
DK
366 }
367 arch = strtok(NULL, " ");
368 }
369 }
b9ed63d3 370 fclose(dpkg);
8aec002f 371 }
b9ed63d3 372 ExecWait(dpkgMultiArch, "dpkg --print-foreign-architectures", true);
8aec002f
DK
373 return archs;
374 }
375
5dd4c8b8
DK
376 if (archs.empty() == true ||
377 std::find(archs.begin(), archs.end(), arch) == archs.end())
bd9d81e3 378 archs.insert(archs.begin(), arch);
3152f4aa
DK
379
380 // erase duplicates and empty strings
381 for (std::vector<string>::reverse_iterator a = archs.rbegin();
382 a != archs.rend(); ++a) {
383 if (a->empty() == true || std::find(a + 1, archs.rend(), *a) != archs.rend())
384 archs.erase(a.base()-1);
385 if (a == archs.rend())
386 break;
387 }
388
5dd4c8b8
DK
389 return archs;
390}
391 /*}}}*/
392// checkArchitecture - are we interested in the given Architecture? /*{{{*/
393bool const Configuration::checkArchitecture(std::string const &Arch) {
394 if (Arch == "all")
395 return true;
396 std::vector<std::string> const archs = getArchitectures(true);
397 return (std::find(archs.begin(), archs.end(), Arch) != archs.end());
398}
399 /*}}}*/
03bef784
DK
400// setDefaultConfigurationForCompressors /*{{{*/
401void Configuration::setDefaultConfigurationForCompressors() {
402 // Set default application paths to check for optional compression types
03bef784 403 _config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
2024154c
DK
404 _config->CndSet("Dir::Bin::xz", "/usr/bin/xz");
405 if (FileExists(_config->FindFile("Dir::Bin::xz")) == true) {
342df712 406 _config->Set("Dir::Bin::lzma", _config->FindFile("Dir::Bin::xz"));
2024154c
DK
407 _config->Set("APT::Compressor::lzma::Binary", "xz");
408 if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
409 _config->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");
410 _config->Set("APT::Compressor::lzma::CompressArg::", "-9");
411 }
412 if (_config->Exists("APT::Compressor::lzma::UncompressArg") == false) {
413 _config->Set("APT::Compressor::lzma::UncompressArg::", "--format=lzma");
414 _config->Set("APT::Compressor::lzma::UncompressArg::", "-d");
415 }
416 } else {
417 _config->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
418 if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
419 _config->Set("APT::Compressor::lzma::CompressArg::", "--suffix=");
420 _config->Set("APT::Compressor::lzma::CompressArg::", "-9");
421 }
422 if (_config->Exists("APT::Compressor::lzma::UncompressArg") == false) {
423 _config->Set("APT::Compressor::lzma::UncompressArg::", "--suffix=");
424 _config->Set("APT::Compressor::lzma::UncompressArg::", "-d");
425 }
426 }
03bef784
DK
427}
428 /*}}}*/
ce7f128c 429// getCompressors - Return Vector of usealbe compressors /*{{{*/
03bef784
DK
430// ---------------------------------------------------------------------
431/* return a vector of compressors used by apt-ftparchive in the
432 multicompress functionality or to detect data.tar files */
433std::vector<APT::Configuration::Compressor>
434const Configuration::getCompressors(bool const Cached) {
435 static std::vector<APT::Configuration::Compressor> compressors;
436 if (compressors.empty() == false) {
437 if (Cached == true)
438 return compressors;
439 else
440 compressors.clear();
441 }
442
443 setDefaultConfigurationForCompressors();
444
e29d7e3e 445 compressors.push_back(Compressor(".", "", "", NULL, NULL, 1));
03bef784
DK
446 if (_config->Exists("Dir::Bin::gzip") == false || FileExists(_config->FindFile("Dir::Bin::gzip")) == true)
447 compressors.push_back(Compressor("gzip",".gz","gzip","-9n","-d",2));
8dd623db
DK
448#ifdef HAVE_ZLIB
449 else
e29d7e3e 450 compressors.push_back(Compressor("gzip",".gz","false", NULL, NULL, 2));
8dd623db 451#endif
03bef784
DK
452 if (_config->Exists("Dir::Bin::bzip2") == false || FileExists(_config->FindFile("Dir::Bin::bzip2")) == true)
453 compressors.push_back(Compressor("bzip2",".bz2","bzip2","-9","-d",3));
c4997486
DK
454#ifdef HAVE_BZ2
455 else
e29d7e3e 456 compressors.push_back(Compressor("bzip2",".bz2","false", NULL, NULL, 3));
c4997486 457#endif
03bef784 458 if (_config->Exists("Dir::Bin::xz") == false || FileExists(_config->FindFile("Dir::Bin::xz")) == true)
2024154c
DK
459 compressors.push_back(Compressor("xz",".xz","xz","-6","-d",4));
460 if (_config->Exists("Dir::Bin::lzma") == false || FileExists(_config->FindFile("Dir::Bin::lzma")) == true)
461 compressors.push_back(Compressor("lzma",".lzma","lzma","-9","-d",5));
03bef784
DK
462
463 std::vector<std::string> const comp = _config->FindVector("APT::Compressor");
464 for (std::vector<std::string>::const_iterator c = comp.begin();
465 c != comp.end(); ++c) {
466 if (*c == "." || *c == "gzip" || *c == "bzip2" || *c == "lzma" || *c == "xz")
467 continue;
468 compressors.push_back(Compressor(c->c_str(), std::string(".").append(*c).c_str(), c->c_str(), "-9", "-d", 100));
469 }
470
471 return compressors;
472}
473 /*}}}*/
b0e1a43f
DK
474// getCompressorExtensions - supported data.tar extensions /*{{{*/
475// ---------------------------------------------------------------------
476/* */
477std::vector<std::string> const Configuration::getCompressorExtensions() {
478 std::vector<APT::Configuration::Compressor> const compressors = getCompressors();
479 std::vector<std::string> ext;
480 for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin();
481 c != compressors.end(); ++c)
482 if (c->Extension.empty() == false && c->Extension != ".")
483 ext.push_back(c->Extension);
484 return ext;
485}
486 /*}}}*/
03bef784
DK
487// Compressor constructor /*{{{*/
488// ---------------------------------------------------------------------
489/* */
490Configuration::Compressor::Compressor(char const *name, char const *extension,
491 char const *binary,
492 char const *compressArg, char const *uncompressArg,
493 unsigned short const cost) {
2024154c 494 std::string const config = std::string("APT::Compressor::").append(name).append("::");
03bef784
DK
495 Name = _config->Find(std::string(config).append("Name"), name);
496 Extension = _config->Find(std::string(config).append("Extension"), extension);
497 Binary = _config->Find(std::string(config).append("Binary"), binary);
498 Cost = _config->FindI(std::string(config).append("Cost"), cost);
499 std::string const compConf = std::string(config).append("CompressArg");
500 if (_config->Exists(compConf) == true)
501 CompressArgs = _config->FindVector(compConf);
502 else if (compressArg != NULL)
503 CompressArgs.push_back(compressArg);
504 std::string const uncompConf = std::string(config).append("UncompressArg");
505 if (_config->Exists(uncompConf) == true)
506 UncompressArgs = _config->FindVector(uncompConf);
507 else if (uncompressArg != NULL)
508 UncompressArgs.push_back(uncompressArg);
509}
510 /*}}}*/
ce7f128c
DK
511// getBuildProfiles - return a vector of enabled build profiles /*{{{*/
512std::vector<std::string> const Configuration::getBuildProfiles() {
513 // order is: override value (~= commandline), environment variable, list (~= config file)
514 std::string profiles_env = getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES");
515 if (profiles_env.empty() == false) {
516 profiles_env = SubstVar(profiles_env, " ", ",");
517 std::string const bp = _config->Find("APT::Build-Profiles");
518 _config->Clear("APT::Build-Profiles");
519 if (bp.empty() == false)
520 _config->Set("APT::Build-Profiles", bp);
521 }
522 return _config->FindVector("APT::Build-Profiles", profiles_env);
523}
524std::string const Configuration::getBuildProfilesString() {
525 std::vector<std::string> profiles = getBuildProfiles();
526 if (profiles.empty() == true)
527 return "";
528 std::vector<std::string>::const_iterator p = profiles.begin();
529 std::string list = *p;
530 for (; p != profiles.end(); ++p)
531 list.append(",").append(*p);
532 return list;
533}
534 /*}}}*/
e878aedb 535}