diff options
author | Sam Bingner <sam@bingner.com> | 2019-12-30 16:31:01 -1000 |
---|---|---|
committer | Sam Bingner <sam@bingner.com> | 2021-03-16 13:10:32 -1000 |
commit | d1027179026357c0db89c7b27dd8d774e34e574b (patch) | |
tree | 46fa7e9ec6831ad383f664541586a463c4181fa8 /apt-pkg | |
parent | 9d8383bdee9f1ddc5685c36678b1ca033cbea971 (diff) |
Add support for JSON output
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/CMakeLists.txt | 3 | ||||
-rw-r--r-- | apt-pkg/algorithms.h | 6 | ||||
-rw-r--r-- | apt-pkg/algorithms.mm (renamed from apt-pkg/algorithms.cc) | 193 |
3 files changed, 155 insertions, 47 deletions
diff --git a/apt-pkg/CMakeLists.txt b/apt-pkg/CMakeLists.txt index 318c6d798..5915a588c 100644 --- a/apt-pkg/CMakeLists.txt +++ b/apt-pkg/CMakeLists.txt @@ -32,7 +32,7 @@ set(APT_PKG_MAJOR ${MAJOR} PARENT_SCOPE) # exporting for methods/CMakeLists.txt # 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" "${CMAKE_CURRENT_BINARY_DIR}/tagfile-keys.cc") +file(GLOB_RECURSE library "*.cc" "*.mm" "${CMAKE_CURRENT_BINARY_DIR}/tagfile-keys.cc") file(GLOB_RECURSE headers "*.h") # Create a library using the C++ files @@ -61,6 +61,7 @@ target_link_libraries(apt-pkg $<$<BOOL:${UDEV_FOUND}>:${UDEV_LIBRARIES}> $<$<BOOL:${SYSTEMD_FOUND}>:${SYSTEMD_LIBRARIES}> ${ICONV_LIBRARIES} + "-framework Foundation" ) set_target_properties(apt-pkg PROPERTIES VERSION ${MAJOR}.${MINOR}) set_target_properties(apt-pkg PROPERTIES SOVERSION ${MAJOR}) diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index c5c9f4c69..5ee5e5f62 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -48,6 +48,9 @@ using std::ostream; #include <apt-pkg/update.h> #include <apt-pkg/upgrade.h> #endif +#ifdef __OBJC__ +#import <Foundation/Foundation.h> +#endif class pkgSimulatePrivate; @@ -87,6 +90,9 @@ public: private: APT_HIDDEN void ShortBreaks(); APT_HIDDEN void Describe(PkgIterator iPkg,std::ostream &out,bool Current,bool Candidate); +#ifdef __OBJC__ + APT_HIDDEN NSMutableDictionary * DescribeJSON(PkgIterator iPkg,bool Current,bool Candidate); +#endif APT_HIDDEN bool RealInstall(PkgIterator Pkg,std::string File); APT_HIDDEN bool RealConfigure(PkgIterator Pkg); APT_HIDDEN bool RealRemove(PkgIterator Pkg,bool Purge); diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.mm index bb0e2f873..4ac63419b 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.mm @@ -32,6 +32,7 @@ #include <string.h> #include <apti18n.h> +NSMutableArray *simulatedOperations = nil; /*}}}*/ using namespace std; @@ -94,6 +95,37 @@ void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candid } } /*}}}*/ +// Simulate::DescribeJSON - Describe a package /*{{{*/ +// --------------------------------------------------------------------- +/* Parameter Current == true displays the current package version, + Parameter Candidate == true displays the candidate package version */ +NSMutableDictionary * pkgSimulate::DescribeJSON(PkgIterator Pkg,bool Current,bool Candidate) +{ + VerIterator Ver(Sim); + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + dictionary[@"Package"] = @(Pkg.FullName(true).c_str()); + + if (Current == true) + { + Ver = Pkg.CurrentVer(); + if (Ver.end() == false){ + dictionary[@"CurrentVersion"] = @(Ver.VerStr()); + } + } + + if (Candidate == true) + { + Ver = Sim[Pkg].CandidateVerIter(Sim); + if (Ver.end() == true) + return dictionary; + dictionary[@"CandidateVersion"] = @(Ver.VerStr()); + dictionary[@"Release"] = @(Ver.RelStr().c_str()); + } + + return dictionary; +} + /*}}}*/ // Simulate::Install - Simulate unpacking of a package /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -106,6 +138,41 @@ bool pkgSimulate::Install(PkgIterator iPkg,string File) } bool pkgSimulate::RealInstall(PkgIterator iPkg,string /*File*/) { + if (_config->FindB("APT::Format::JSON", false)){ + // Adapt the iterator + PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); + Flags[Pkg->ID] = 1; + + NSMutableDictionary *package = DescribeJSON(Pkg, true, true); + package[@"Type"] = @"Inst"; + [simulatedOperations addObject:package]; + + Sim.MarkInstall(Pkg,false); + + // Look for broken conflicts+predepends. + for (PkgIterator I = Sim.PkgBegin(); I.end() == false; ++I) + { + if (Sim[I].InstallVer == 0) + continue; + + for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false;) + { + DepIterator Start; + DepIterator End; + D.GlobOr(Start,End); + if (Start.IsNegative() == true || End->Type == pkgCache::Dep::PreDepends) + { + if ((Sim[End] & pkgDepCache::DepGInstall) == 0) + { + if (Start->Type == pkgCache::Dep::Conflicts) + _error->Error("Fatal, conflicts violated %s",I.FullName(false).c_str()); + } + } + } + } + return true; + } + // Adapt the iterator PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch()); Flags[Pkg->ID] = 1; @@ -164,42 +231,48 @@ bool pkgSimulate::RealConfigure(PkgIterator iPkg) Flags[Pkg->ID] = 2; - if (Sim[Pkg].InstBroken() == true) - { - cout << "Conf " << Pkg.FullName(false) << " broken" << endl; + if (_config->FindB("APT::Format::JSON", false)){ + NSMutableDictionary *package = DescribeJSON(Pkg, false, true); + package[@"Type"] = @"Conf"; + [simulatedOperations addObject:package]; + } else { + if (Sim[Pkg].InstBroken() == true) + { + cout << "Conf " << Pkg.FullName(false) << " broken" << endl; - Sim.Update(); - - // Print out each package and the failed dependencies - for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; ++D) + Sim.Update(); + + // Print out each package and the failed dependencies + for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; ++D) + { + if (Sim.IsImportantDep(D) == false || + (Sim[D] & pkgDepCache::DepInstall) != 0) + continue; + + if (D->Type == pkgCache::Dep::Obsoletes) + cout << " Obsoletes:" << D.TargetPkg().FullName(false); + else if (D->Type == pkgCache::Dep::Conflicts) + cout << " Conflicts:" << D.TargetPkg().FullName(false); + else if (D->Type == pkgCache::Dep::DpkgBreaks) + cout << " Breaks:" << D.TargetPkg().FullName(false); + else + cout << " Depends:" << D.TargetPkg().FullName(false); + } + cout << endl; + + _error->Error("Conf Broken %s",Pkg.FullName(false).c_str()); + } + else { - if (Sim.IsImportantDep(D) == false || - (Sim[D] & pkgDepCache::DepInstall) != 0) - continue; - - if (D->Type == pkgCache::Dep::Obsoletes) - cout << " Obsoletes:" << D.TargetPkg().FullName(false); - else if (D->Type == pkgCache::Dep::Conflicts) - cout << " Conflicts:" << D.TargetPkg().FullName(false); - else if (D->Type == pkgCache::Dep::DpkgBreaks) - cout << " Breaks:" << D.TargetPkg().FullName(false); - else - cout << " Depends:" << D.TargetPkg().FullName(false); - } - cout << endl; + cout << "Conf "; + Describe(Pkg,cout,false,true); + } - _error->Error("Conf Broken %s",Pkg.FullName(false).c_str()); - } - else - { - cout << "Conf "; - Describe(Pkg,cout,false,true); + if (Sim.BrokenCount() != 0) + ShortBreaks(); + else + cout << endl; } - - if (Sim.BrokenCount() != 0) - ShortBreaks(); - else - cout << endl; return true; } @@ -227,16 +300,26 @@ bool pkgSimulate::RealRemove(PkgIterator iPkg,bool Purge) Flags[Pkg->ID] = 3; Sim.MarkDelete(Pkg); - if (Purge == true) - cout << "Purg "; - else - cout << "Remv "; - Describe(Pkg,cout,true,false); + if (_config->FindB("APT::Format::JSON", false)){ + NSMutableDictionary *package = DescribeJSON(Pkg, true, false); + if (Purge == true) + package[@"Type"] = @"Purg"; + else + package[@"Type"] = @"Remv"; - if (Sim.BrokenCount() != 0) - ShortBreaks(); - else - cout << endl; + [simulatedOperations addObject:package]; + } else { + if (Purge == true) + cout << "Purg "; + else + cout << "Remv "; + Describe(Pkg,cout,true,false); + + if (Sim.BrokenCount() != 0) + ShortBreaks(); + else + cout << endl; + } return true; } @@ -262,26 +345,33 @@ void pkgSimulate::ShortBreaks() /*}}}*/ bool pkgSimulate::Go2(APT::Progress::PackageManager *) /*{{{*/ { + bool rv = true; if (pkgDPkgPM::ExpandPendingCalls(d->List, Cache) == false) return false; + BOOL doJSON = _config->FindB("APT::Format::JSON", false); + if (doJSON) { + simulatedOperations = [NSMutableArray array]; + } else { + simulatedOperations = nil; + } for (auto && I : d->List) switch (I.Op) { case pkgDPkgPM::Item::Install: if (RealInstall(I.Pkg, I.File) == false) - return false; + goto failout; break; case pkgDPkgPM::Item::Configure: if (RealConfigure(I.Pkg) == false) - return false; + goto failout; break; case pkgDPkgPM::Item::Remove: if (RealRemove(I.Pkg, false) == false) - return false; + goto failout; break; case pkgDPkgPM::Item::Purge: if (RealRemove(I.Pkg, true) == false) - return false; + goto failout; break; case pkgDPkgPM::Item::ConfigurePending: case pkgDPkgPM::Item::TriggersPending: @@ -289,7 +379,18 @@ bool pkgSimulate::Go2(APT::Progress::PackageManager *) /*{{{*/ case pkgDPkgPM::Item::PurgePending: return _error->Error("Internal error, simulation encountered unexpected pending item"); } - return true; + if (false) { +failout: + rv = false; + } + if (doJSON && simulatedOperations != nil) { + NSData *data = [NSJSONSerialization dataWithJSONObject:@{@"operations": simulatedOperations} options:NSJSONWritingPrettyPrinted error:nil]; + simulatedOperations = nil; + NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput]; + [stdout writeData:data]; + cout << endl << flush; + } + return rv; } /*}}}*/ // ApplyStatus - Adjust for non-ok packages /*{{{*/ |