diff options
author | Sam Bingner <sam@bingner.com> | 2019-12-30 16:31:01 -1000 |
---|---|---|
committer | Sam Bingner <sam@bingner.com> | 2019-12-30 23:10:02 -1000 |
commit | bfe83a62a27bbe8ee960749ff78735a91624f05a (patch) | |
tree | f3b15533444d7313d6118ad2deb4007e05844f05 /apt-private | |
parent | 343cbbac912d9de5c72388bfc4c3bbbcb81506df (diff) |
Add support for JSON output
Diffstat (limited to 'apt-private')
-rw-r--r-- | apt-private/CMakeLists.txt | 4 | ||||
-rw-r--r-- | apt-private/private-output.mm (renamed from apt-private/private-output.cc) | 163 |
2 files changed, 161 insertions, 6 deletions
diff --git a/apt-private/CMakeLists.txt b/apt-private/CMakeLists.txt index 88a8f97fe..4a6ea51b8 100644 --- a/apt-private/CMakeLists.txt +++ b/apt-private/CMakeLists.txt @@ -5,14 +5,14 @@ set(MINOR 0) # Definition of the C++ files used to build the library - note that this # is expanded at CMake time, so you have to rerun cmake if you add or remove # a file (you can just run cmake . in the build directory) -file(GLOB_RECURSE library "*.cc") +file(GLOB_RECURSE library "*.cc" "*.mm") file(GLOB_RECURSE headers "*.h") # Create a library using the C++ files add_library(apt-private SHARED ${library}) # Link the library and set the SONAME -target_link_libraries(apt-private PUBLIC apt-pkg) +target_link_libraries(apt-private PUBLIC apt-pkg "-framework Foundation") set_target_properties(apt-private PROPERTIES VERSION ${MAJOR}.${MINOR}) set_target_properties(apt-private PROPERTIES SOVERSION ${MAJOR}) set_target_properties(apt-private PROPERTIES CXX_VISIBILITY_PRESET hidden) diff --git a/apt-private/private-output.cc b/apt-private/private-output.mm index eb9a34abe..2cf3dc656 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.mm @@ -1,6 +1,8 @@ // Include files /*{{{*/ #include <config.h> +#include <Foundation/Foundation.h> + #include <apt-pkg/cachefile.h> #include <apt-pkg/configuration.h> #include <apt-pkg/depcache.h> @@ -443,15 +445,150 @@ static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache } } } + +static NSMutableDictionary * BrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now) +{ + if (Now == true) + { + if ((*Cache)[Pkg].NowBroken() == false) + return nil; + } + else + { + if ((*Cache)[Pkg].InstBroken() == false) + return nil; + } + + NSMutableDictionary *packages = [NSMutableDictionary dictionary]; + + // Array of depends for package + NSMutableArray *deps = [NSMutableArray array]; + + // Print out each package and the failed dependencies + packages[@(Pkg.FullName(true).c_str())] = deps; + + pkgCache::VerIterator Ver; + + if (Now == true) + Ver = Pkg.CurrentVer(); + else + Ver = (*Cache)[Pkg].InstVerIter(*Cache); + + if (Ver.end() == true) + { + return packages; + } + + for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) + { + // Compute a single dependency element (glob or) + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); // advances D + + if ((*Cache)->IsImportantDep(End) == false) + continue; + + if (Now == true) + { + if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow) + continue; + } + else + { + if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) + continue; + } + + // Array of depends that can satisfy this depend + NSMutableArray *possibleDepends = [NSMutableArray array]; + [deps addObject:possibleDepends]; + + while (1) + { + + NSMutableDictionary *dependency = [NSMutableDictionary dictionary]; + dependency[@"Type"] = @(End.DepType()); + dependency[@"Package"] = @(Start.TargetPkg().FullName(true).c_str()); + + // Show a quick summary of the version requirements + if (Start.TargetVer() != 0) { + dependency[@"VersionSummary"] = [NSString stringWithFormat:@"%s %s", Start.CompType(), Start.TargetVer()]; + dependency[@"CompType"] = @(Start.CompType()); + dependency[@"TargetVer"] = @(Start.TargetVer()); + } + + /* Show a summary of the target package if possible. In the case + of virtual packages we show nothing */ + pkgCache::PkgIterator Targ = Start.TargetPkg(); + if (Targ->ProvidesList == 0) + { + pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache); + if (Now == true) + Ver = Targ.CurrentVer(); + + if (Ver.end() == false) + { + dependency[@"VerStr"] = @(Ver.VerStr()); + if (Now == true) + dependency[@"Reason"] = [NSString stringWithFormat:@"%s is installed",Ver.VerStr()]; + else + dependency[@"Reason"] = [NSString stringWithFormat:@"%s is to be installed",Ver.VerStr()]; + } + else + { + if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true) + { + if (Targ->ProvidesList == 0) + dependency[@"Reason"] = @"it is not installable"; + else + dependency[@"Reason"] = @"it is a virtual package"; + } + else { + if (Now) + dependency[@"Reason"] = @"it is not installed"; + else + dependency[@"Reason"] = @"it is not going to be installed"; + } + } + } + + [possibleDepends addObject:dependency]; + if (Start == End) + break; + ++Start; + } + } + return packages; +} + void ShowBroken(ostream &out, CacheFile &Cache, bool const Now) { if (Cache->BrokenCount() == 0) return; out << _("The following packages have unmet dependencies:") << endl; + + bool useJSON = _config->FindB("APT::Format::JSON", false); + SortedPackageUniverse Universe(Cache); - for (auto const &Pkg: Universe) - ShowBrokenPackage(out, &Cache, Pkg, Now); + + if (useJSON){ + NSMutableDictionary *packages = [NSMutableDictionary dictionary]; + for (auto const &Pkg: Universe){ + NSMutableDictionary *package = BrokenPackage(out, &Cache, Pkg, Now); + [packages addEntriesFromDictionary:package]; + } + + NSData *data = [NSJSONSerialization dataWithJSONObject:@{@"brokenPackages": packages} options:NSJSONWritingPrettyPrinted error:nil]; + NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput]; + [stdout writeData:data]; + + cout << endl << flush; + } else { + for (auto const &Pkg: Universe) + ShowBrokenPackage(out, &Cache, Pkg, Now); + } } void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) { @@ -459,9 +596,27 @@ void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) return; out << _("The following packages have unmet dependencies:") << endl; + + bool useJSON = _config->FindB("APT::Format::JSON", false); + APT::PackageUniverse Universe(Cache); - for (auto const &Pkg: Universe) - ShowBrokenPackage(out, &Cache, Pkg, Now); + + if (useJSON){ + NSMutableDictionary *packages = [NSMutableDictionary dictionary]; + for (auto const &Pkg: Universe){ + NSMutableDictionary *package = BrokenPackage(out, &Cache, Pkg, Now); + [packages addEntriesFromDictionary:package]; + } + + NSData *data = [NSJSONSerialization dataWithJSONObject:@{@"brokenPackages": packages} options:NSJSONWritingPrettyPrinted error:nil]; + NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput]; + [stdout writeData:data]; + + cout << endl << flush; + } else { + for (auto const &Pkg: Universe) + ShowBrokenPackage(out, &Cache, Pkg, Now); + } } /*}}}*/ // ShowNew - Show packages to newly install /*{{{*/ |