1 // -*- mode: cpp; mode: fold -*- 
   3 /* ##################################################################### 
   5    cover around the internal solver to be able to run it like an external 
   7    ##################################################################### */ 
   9 // Include Files                                                        /*{{{*/ 
  12 #include <apt-pkg/error.h> 
  13 #include <apt-pkg/cmndline.h> 
  14 #include <apt-pkg/init.h> 
  15 #include <apt-pkg/cachefile.h> 
  16 #include <apt-pkg/cacheset.h> 
  17 #include <apt-pkg/strutl.h> 
  18 #include <apt-pkg/edsp.h> 
  19 #include <apt-pkg/fileutl.h> 
  20 #include <apt-pkg/pkgsystem.h> 
  21 #include <apt-pkg/configuration.h> 
  22 #include <apt-pkg/packagemanager.h> 
  23 #include <apt-pkg/prettyprinters.h> 
  24 #include <apt-pkg/depcache.h> 
  25 #include <apt-pkg/pkgcache.h> 
  26 #include <apt-pkg/cacheiterators.h> 
  28 #include <apt-private/private-output.h> 
  29 #include <apt-private/private-cmndline.h> 
  30 #include <apt-private/private-main.h> 
  44 static bool ShowHelp(CommandLine 
&)                                     /*{{{*/ 
  47                 _("Usage: apt-internal-planner\n" 
  49                 "apt-internal-planner is an interface to use the current internal\n" 
  50                 "installation planner for the APT family like an external one,\n" 
  51                 "for debugging or the like.\n"); 
  55 APT_NORETURN 
static void DIE(std::string 
const &message
) {              /*{{{*/ 
  56         std::cerr 
<< "ERROR: " << message 
<< std::endl
; 
  57         _error
->DumpErrors(std::cerr
); 
  61 static std::vector
<aptDispatchWithHelp
> GetCommands()                   /*{{{*/ 
  66 class PMOutput
: public pkgPackageManager                                
/*{{{*/ 
  72    virtual bool Install(PkgIterator Pkg
,std::string
) APT_OVERRIDE
 
  74       //std::cerr << "INSTALL: " << APT::PrettyPkg(&Cache, Pkg) << std::endl; 
  75       return EDSP::WriteSolutionStanza(output
, "Unpack", Cache
[Pkg
].InstVerIter(Cache
)); 
  77    virtual bool Configure(PkgIterator Pkg
) APT_OVERRIDE
 
  79       //std::cerr << "CONFIGURE: " << APT::PrettyPkg(&Cache, Pkg) << " " << std::endl; 
  80       return EDSP::WriteSolutionStanza(output
, "Configure", Cache
[Pkg
].InstVerIter(Cache
)); 
  82    virtual bool Remove(PkgIterator Pkg
,bool) APT_OVERRIDE
 
  84       //std::cerr << "REMOVE: " << APT::PrettyPkg(&Cache, Pkg) << " " << std::endl; 
  85       return EDSP::WriteSolutionStanza(output
, "Remove", Pkg
.CurrentVer()); 
  88    PMOutput(pkgDepCache 
*Cache
, FileFd 
&file
) : pkgPackageManager(Cache
), output(file
), 
  89       Debug(_config
->FindB("Debug::EDSP::WriteSolution", false)) 
  92    bool ApplyRequest(std::list
<std::pair
<std::string
,EIPP::PKG_ACTION
>> const &actions
) 
  94       for (auto && a
: actions
) 
  96          auto const Pkg 
= Cache
.FindPkg(a
.first
); 
  97          if (unlikely(Pkg
.end() == true)) 
 101             case EIPP::PKG_ACTION::NOOP
: 
 103             case EIPP::PKG_ACTION::INSTALL
: 
 104             case EIPP::PKG_ACTION::REINSTALL
: 
 105                FileNames
[Pkg
->ID
] = "EIPP"; 
 107             case EIPP::PKG_ACTION::REMOVE
: 
 115 int main(int argc
,const char *argv
[])                                   /*{{{*/ 
 117         // we really don't need anything 
 121         ParseCommandLine(CmdL
, APT_CMD::APT_INTERNAL_PLANNER
, &_config
, NULL
, argc
, argv
, &ShowHelp
, &GetCommands
); 
 123         // Deal with stdout not being a tty 
 124         if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1) 
 125                 _config
->Set("quiet","1"); 
 127         if (_config
->FindI("quiet", 0) < 1) 
 128                 _config
->Set("Debug::EIPP::WriteSolution", true); 
 130         _config
->Set("APT::System", "Debian APT planner interface"); 
 131         _config
->Set("APT::Planner", "internal"); 
 132         _config
->Set("eipp::scenario", "/nonexistent/stdin"); 
 134         if (output
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly 
| FileFd::BufferedWrite
, true) == false) 
 135            DIE("stdout couldn't be opened"); 
 136         int const input 
= STDIN_FILENO
; 
 137         SetNonBlock(input
, false); 
 139         EDSP::WriteProgress(0, "Start up planner…", output
); 
 141         if (pkgInitSystem(*_config
,_system
) == false) 
 142                 DIE("System could not be initialized!"); 
 144         EDSP::WriteProgress(1, "Read request…", output
); 
 146         if (WaitFd(input
, false, 5) == false) 
 147                 DIE("WAIT timed out in the planner"); 
 149         std::list
<std::pair
<std::string
,EIPP::PKG_ACTION
>> actions
; 
 151         if (EIPP::ReadRequest(input
, actions
, flags
) == false) 
 152                 DIE("Parsing the request failed!"); 
 153         _config
->Set("APT::Immediate-Configure", (flags 
& EIPP::Request::NO_IMMEDIATE_CONFIGURATION
) == 0); 
 154         _config
->Set("APT::Immediate-Configure-All", (flags 
& EIPP::Request::IMMEDIATE_CONFIGURATION_ALL
) != 0); 
 155         _config
->Set("APT::Force-LoopBreak", (flags 
& EIPP::Request::ALLOW_TEMPORARY_REMOVE_OF_ESSENTIALS
) != 0); 
 157         EDSP::WriteProgress(5, "Read scenario…", output
); 
 159         pkgCacheFile CacheFile
; 
 160         if (CacheFile
.Open(NULL
, false) == false) 
 161                 DIE("Failed to open CacheFile!"); 
 163         EDSP::WriteProgress(50, "Apply request on scenario…", output
); 
 165         if (EIPP::ApplyRequest(actions
, CacheFile
) == false) 
 166                 DIE("Failed to apply request to depcache!"); 
 168         EDSP::WriteProgress(60, "Call orderinstall on current scenario…", output
); 
 170         //_config->Set("Debug::pkgOrderList", true); 
 171         //_config->Set("Debug::pkgPackageManager", true); 
 172         PMOutput 
PM(CacheFile
, output
); 
 173         if (PM
.ApplyRequest(actions
) == false) 
 174                 DIE("Failed to apply request to packagemanager!"); 
 175         pkgPackageManager::OrderResult 
const Res 
= PM
.DoInstallPreFork(); 
 176         std::ostringstream broken
; 
 179            case pkgPackageManager::Completed
: 
 180               EDSP::WriteProgress(100, "Done", output
); 
 182            case pkgPackageManager::Incomplete
: 
 183               broken 
<< "Planner could only incompletely plan an installation order!" << std::endl
; 
 184               _error
->DumpErrors(broken
, GlobalError::DEBUG
); 
 185               EDSP::WriteError("pm-incomplete", broken
.str(), output
); 
 187            case pkgPackageManager::Failed
: 
 188               broken 
<< "Planner failed to find an installation order!" << std::endl
; 
 189               _error
->DumpErrors(broken
, GlobalError::DEBUG
); 
 190               EDSP::WriteError("pm-failed", broken
.str(), output
); 
 194         return DispatchCommandLine(CmdL
, {});