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