1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
#include "dpkgparser.h"
#include <sstream>
#include "packagename.h"
#include "runcommandforparsing.h"
namespace NApt {
/** parse a line of dpkg -l and return a pair(packageName, version)
*/
const DpkgParser::PackageInformation parseDpkgLine(const string& line) {
std::istringstream stream(line);
std::string word;
std::string package;
std::string version;
std::string architecture;
std::string description;
for (int i = 0; i < 5 && stream; ++i) {
// should not happen, but to improve robustness provide some fallback
if (!(stream >> word))
break;
switch (i) {
case 0:
// ignore, should be "ii"
break;
case 1: {
string packageName = PackageName::extractArchitecture(word).name;
package = packageName;
break;
}
case 2:
version = word;
break;
case 3:
architecture = word;
// skip whitespace and put the rest into description
std::getline(stream >> std::ws, description);
break;
}
}
return DpkgParser::PackageInformation {
.name = package,
.version = version,
.architecture = architecture,
.description = description
};
}
void mergeIntoPackages(
const DpkgParser::PackageInformation& package,
map<string, const DpkgParser::PackageInformation>& target
) {
auto packageIterator = target.find(package.name);
if (packageIterator == target.end()) {
target.insert({package.name, package});
} else if (package.architecture == PackageName::defaultArchitecture()) {
// replace only, if we have the target architecture
// c++ speciality: we have to first remove the old, then add the
// new entry, if the value type is const
target.erase(packageIterator);
target.insert({package.name, package});
}
}
map<string, const DpkgParser::PackageInformation> DpkgParser::getInstalledPackages() {
map<string, const PackageInformation> packages;
auto lineProcessor = [&packages](const string& line) {
auto package = parseDpkgLine(line);
if (!package.name.empty()) {
mergeIntoPackages(package, packages);
}
};
NApplication::runCommandForParsing("dpkg -l |grep -E \"^ii\"", lineProcessor);
return packages;
}
} // NApt
|