summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorSam Bingner <sam@bingner.com>2019-12-30 16:31:01 -1000
committerSam Bingner <sam@bingner.com>2021-03-16 13:10:32 -1000
commitd1027179026357c0db89c7b27dd8d774e34e574b (patch)
tree46fa7e9ec6831ad383f664541586a463c4181fa8 /apt-pkg
parent9d8383bdee9f1ddc5685c36678b1ca033cbea971 (diff)
Add support for JSON output
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/CMakeLists.txt3
-rw-r--r--apt-pkg/algorithms.h6
-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 /*{{{*/