X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/796673c38509300c988fbba2f2679ba3c76916db..12841e8320aa499554ac50b102b222900bb1b879:/apt-private/private-output.cc?ds=sidebyside

diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc
index a8bbad9e5..fc76a05bc 100644
--- a/apt-private/private-output.cc
+++ b/apt-private/private-output.cc
@@ -7,15 +7,23 @@
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/policy.h>
+#include <apt-pkg/depcache.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cacheiterators.h>
 
+#include <apt-private/private-output.h>
+#include <apt-private/private-cachefile.h>
+
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <iomanip>
 #include <iostream>
-#include <locale.h>
 #include <langinfo.h>
 #include <unistd.h>
-
-#include "private-output.h"
-#include "private-cachefile.h"
+#include <signal.h>
+#include <sys/ioctl.h>
 
 #include <apti18n.h>
 									/*}}}*/
@@ -26,10 +34,29 @@ std::ostream c0out(0);
 std::ostream c1out(0);
 std::ostream c2out(0);
 std::ofstream devnull("/dev/null");
+
+
 unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
 
+// SigWinch - Window size change signal handler				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static void SigWinch(int)
+{
+   // Riped from GNU ls
+#ifdef TIOCGWINSZ
+   struct winsize ws;
+  
+   if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
+      ScreenWidth = ws.ws_col - 1;
+#endif
+}
+									/*}}}*/
 bool InitOutput()							/*{{{*/
 {
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
+      _config->Set("quiet","1");
+
    c0out.rdbuf(cout.rdbuf());
    c1out.rdbuf(cout.rdbuf());
    c2out.rdbuf(cout.rdbuf());
@@ -38,6 +65,10 @@ bool InitOutput()							/*{{{*/
    if (_config->FindI("quiet",0) > 1)
       c1out.rdbuf(devnull.rdbuf());
 
+   // deal with window size changes
+   signal(SIGWINCH,SigWinch);
+   SigWinch(0);
+
    if(!isatty(1))
    {
       _config->Set("APT::Color", "false");
@@ -60,16 +91,18 @@ bool InitOutput()							/*{{{*/
    return true;
 }
 									/*}}}*/
-std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) /*{{{*/
+static std::string GetArchiveSuite(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator ver) /*{{{*/
 {
    std::string suite = "";
-   if (ver && ver.FileList() && ver.FileList())
+   if (ver && ver.FileList())
    {
       pkgCache::VerFileIterator VF = ver.FileList();
       for (; VF.end() == false ; ++VF)
       {
-         // XXX: how to figure out the relevant suite? if its in multiple ones?
-         suite = suite + "," + VF.File().Archive();
+         if(VF.File() == NULL || VF.File().Archive() == NULL)
+            suite = suite + "," + _("unknown");
+         else
+            suite = suite + "," + VF.File().Archive();
          //suite = VF.File().Archive();
       }
       suite = suite.erase(0, 1);
@@ -77,7 +110,7 @@ std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver)
    return suite;
 }
 									/*}}}*/
-std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
+static std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgDepCache *DepCache = CacheFile.GetDepCache();
    pkgDepCache::StateCache &state = (*DepCache)[P];
@@ -85,7 +118,7 @@ std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
    std::string flags_str;
    if (state.NowBroken())
       flags_str = "B";
-   if (P.CurrentVer() && state.Upgradable())
+   if (P.CurrentVer() && state.Upgradable() && state.CandidateVer != NULL)
       flags_str = "g";
    else if (P.CurrentVer() != NULL)
       flags_str = "i";
@@ -94,7 +127,7 @@ std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
    return flags_str;
 }
 									/*}}}*/
-std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
+static std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgPolicy *policy = CacheFile.GetPolicy();
    pkgCache::VerIterator cand = policy->GetCandidateVer(P);
@@ -102,14 +135,14 @@ std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P
    return cand ? cand.VerStr() : "(none)";
 }
 									/*}}}*/
-std::string GetInstalledVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
+static std::string GetInstalledVersion(pkgCacheFile &/*CacheFile*/, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgCache::VerIterator inst = P.CurrentVer();
 
    return inst ? inst.VerStr() : "(none)";
 }
 									/*}}}*/
-std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)/*{{{*/
+static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator V)/*{{{*/
 {
    pkgCache::PkgIterator P = V.ParentPkg();
    if (V == P.CurrentVer())
@@ -129,16 +162,31 @@ std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)/*{{{*/
    return "(none)";
 }
 									/*}}}*/
-std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
+static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
-   pkgPolicy *policy = CacheFile.GetPolicy();
-   pkgCache::VerIterator inst = P.CurrentVer();
-   pkgCache::VerIterator cand = policy->GetCandidateVer(P);
-   
-   return inst ? inst.Arch() : cand.Arch();
+   if (P->CurrentVer == 0)
+   {
+      pkgDepCache * const DepCache = CacheFile.GetDepCache();
+      pkgDepCache::StateCache const &state = (*DepCache)[P];
+      if (state.CandidateVer != NULL)
+      {
+	 pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer);
+	 return CandV.Arch();
+      }
+      else
+      {
+	 pkgCache::VerIterator const V = P.VersionList();
+	 if (V.end() == false)
+	    return V.Arch();
+	 else
+	    return P.Arch();
+      }
+   }
+   else
+      return P.CurrentVer().Arch();
 }
 									/*}}}*/
-std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
+static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgPolicy *policy = CacheFile.GetPolicy();
 
@@ -159,81 +207,90 @@ std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pk
    return ShortDescription;
 }
 									/*}}}*/
-void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
-                       pkgCache::VerIterator V, std::ostream &out,
-                       bool include_summary)
+static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 {
-   pkgCache::PkgIterator P = V.ParentPkg();
+   pkgPolicy *policy = CacheFile.GetPolicy();
 
-   pkgDepCache *DepCache = CacheFile.GetDepCache();
-   pkgDepCache::StateCache &state = (*DepCache)[P];
+   pkgCache::VerIterator ver;
+   if (P->CurrentVer != 0)
+      ver = P.CurrentVer();
+   else
+      ver = policy->GetCandidateVer(P);
 
-   std::string suite = GetArchiveSuite(CacheFile, V);
-   std::string name_str = P.Name();
+   std::string const EmptyDescription = "(none)";
+   if(ver.end() == true)
+      return EmptyDescription;
+
+   pkgCache::DescIterator const Desc = ver.TranslatedDescription();
+   pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
+   std::string const longdesc = parser.LongDesc();
+   if (longdesc.empty() == true)
+      return EmptyDescription;
+   return SubstVar(longdesc, "\n ", "\n  ");
+}
+									/*}}}*/
+void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
+                       pkgCache::VerIterator const &V, std::ostream &out,
+                       std::string const &format)
+{
+   pkgCache::PkgIterator const P = V.ParentPkg();
+   pkgDepCache * const DepCache = CacheFile.GetDepCache();
+   pkgDepCache::StateCache const &state = (*DepCache)[P];
 
+   std::string output;
    if (_config->FindB("APT::Cmd::use-format", false))
+      output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
+   else
+      output = format;
+
+   // FIXME: some of these names are really icky – and all is nowhere documented
+   output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
+   output = SubstVar(output, "${Package}", P.Name());
+   std::string const ArchStr = GetArchitecture(CacheFile, P);
+   output = SubstVar(output, "${Architecture}", ArchStr);
+   std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P);
+   output = SubstVar(output, "${installed:Version}", InstalledVerStr);
+   std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P);
+   output = SubstVar(output, "${candidate:Version}", CandidateVerStr);
+   std::string const VersionStr = GetVersion(CacheFile, V);
+   output = SubstVar(output, "${Version}", VersionStr);
+   output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
+
+   std::string StatusStr = "";
+   if (P->CurrentVer != 0)
    {
-      std::string format = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
-      std::string output = format;
-   
-      output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
-      output = SubstVar(output, "${Package}", name_str);
-      output = SubstVar(output, "${installed:Version}", GetInstalledVersion(CacheFile, P));
-      output = SubstVar(output, "${candidate:Version}", GetCandidateVersion(CacheFile, P));
-      output = SubstVar(output, "${Version}", GetVersion(CacheFile, V));
-      output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
-      output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
-      out << output << std::endl;
-   } else {
-      // raring/linux-kernel version [upradable: new-version]
-      //    description
-      pkgPolicy *policy = CacheFile.GetPolicy();
-      out << std::setiosflags(std::ios::left)
-          << _config->Find("APT::Color::Highlight", "")
-          << name_str 
-          << _config->Find("APT::Color::Neutral", "")
-          << "/" << suite
-          << " ";
-      if(P.CurrentVer() == V && state.Upgradable()) {
-         out << GetVersion(CacheFile, V)
-             << " "
-             << "[" << _("installed,upgradable to: ")
-             << GetCandidateVersion(CacheFile, P) << "]";
-      } else if (P.CurrentVer() == V) {
-         out << GetVersion(CacheFile, V)
-             << " ";
-         if(!V.Downloadable())
-            out << _("[installed,local]");
-         else
-            if(V.Automatic() && state.Garbage)
-                  out << _("[installed,auto-removable]");
-            else if (state.Flags & pkgCache::Flag::Auto)
-               out << _("[installed,automatic]");
-            else
-               out << _("[installed]");
-      } else if (P.CurrentVer() && 
-                 policy->GetCandidateVer(P) == V && 
-                 state.Upgradable()) {
-         out << GetVersion(CacheFile, V)
-             << " "
-             << _("[upgradable from: ")
-             << GetInstalledVersion(CacheFile, P) << "]";
-      } else {
-         if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
-            out << GetVersion(CacheFile, V) 
-                << " "
-                << _("[residual-config]");
-         else
-            out << GetVersion(CacheFile, V);
-      }
-      out << " " << GetArchitecture(CacheFile, P);
-      if (include_summary)
+      if (P.CurrentVer() == V)
       {
-         out << std::endl 
-             << "  " << GetShortDescription(CacheFile, records, P)
-             << std::endl;
+	 if (state.Upgradable() && state.CandidateVer != NULL)
+	    strprintf(StatusStr, _("[installed,upgradable to: %s]"),
+		  CandidateVerStr.c_str());
+	 else if (V.Downloadable() == false)
+	    StatusStr = _("[installed,local]");
+	 else if(V.Automatic() == true && state.Garbage == true)
+	    StatusStr = _("[installed,auto-removable]");
+	 else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+	    StatusStr = _("[installed,automatic]");
+	 else
+	    StatusStr = _("[installed]");
       }
+      else if (state.CandidateVer == V && state.Upgradable())
+	 strprintf(StatusStr, _("[upgradable from: %s]"),
+	       InstalledVerStr.c_str());
    }
+   else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
+      StatusStr = _("[residual-config]");
+   output = SubstVar(output, "${apt:Status}", StatusStr);
+   output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", ""));
+   output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", ""));
+   output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
+   output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
+   output = SubstVar(output, "${ }${ }", "${ }");
+   output = SubstVar(output, "${ }\n", "\n");
+   output = SubstVar(output, "${ }", " ");
+   if (APT::String::Endswith(output, " ") == true)
+      output.erase(output.length() - 1);
+
+   out << output;
 }
 									/*}}}*/
 // ShowList - Show a list						/*{{{*/
@@ -308,129 +365,141 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList)
            Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
            Depends: libsasl7 but it is not going to be installed   
  */
-void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
+static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
 {
-   if (Cache->BrokenCount() == 0)
+   if (Now == true)
+   {
+      if ((*Cache)[Pkg].NowBroken() == false)
+	 return;
+   }
+   else
+   {
+      if ((*Cache)[Pkg].InstBroken() == false)
+	 return;
+   }
+
+   // Print out each package and the failed dependencies
+   out << " " << Pkg.FullName(true) << " :";
+   unsigned const Indent = Pkg.FullName(true).size() + 3;
+   bool First = true;
+   pkgCache::VerIterator Ver;
+
+   if (Now == true)
+      Ver = Pkg.CurrentVer();
+   else
+      Ver = (*Cache)[Pkg].InstVerIter(*Cache);
+
+   if (Ver.end() == true)
+   {
+      out << endl;
       return;
+   }
 
-   out << _("The following packages have unmet dependencies:") << endl;
-   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
    {
-      pkgCache::PkgIterator I(Cache,Cache.List[J]);
-      
+      // 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[I].NowBroken() == false)
+	 if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
 	    continue;
       }
       else
       {
-	 if (Cache[I].InstBroken() == false)
+	 if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
 	    continue;
       }
-      
-      // Print out each package and the failed dependencies
-      out << " " << I.FullName(true) << " :";
-      unsigned const Indent = I.FullName(true).size() + 3;
-      bool First = true;
-      pkgCache::VerIterator Ver;
-      
-      if (Now == true)
-	 Ver = I.CurrentVer();
-      else
-	 Ver = Cache[I].InstVerIter(Cache);
-      
-      if (Ver.end() == true)
-      {
-	 out << endl;
-	 continue;
-      }
-      
-      for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
+
+      bool FirstOr = true;
+      while (1)
       {
-	 // Compute a single dependency element (glob or)
-	 pkgCache::DepIterator Start;
-	 pkgCache::DepIterator End;
-	 D.GlobOr(Start,End); // advances D
+	 if (First == false)
+	    for (unsigned J = 0; J != Indent; J++)
+	       out << ' ';
+	 First = false;
 
-	 if (Cache->IsImportantDep(End) == false)
-	    continue;
-	 
-	 if (Now == true)
+	 if (FirstOr == false)
 	 {
-	    if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
-	       continue;
+	    for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
+	       out << ' ';
 	 }
 	 else
+	    out << ' ' << End.DepType() << ": ";
+	 FirstOr = false;
+
+	 out << Start.TargetPkg().FullName(true);
+
+	 // Show a quick summary of the version requirements
+	 if (Start.TargetVer() != 0)
+	    out << " (" << Start.CompType() << " " << 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)
 	 {
-	    if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
-	       continue;
-	 }
-	 
-	 bool FirstOr = true;
-	 while (1)
-	 {
-	    if (First == false)
-	       for (unsigned J = 0; J != Indent; J++)
-		  out << ' ';
-	    First = false;
+	    out << ' ';
+	    pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
+	    if (Now == true)
+	       Ver = Targ.CurrentVer();
 
-	    if (FirstOr == false)
+	    if (Ver.end() == false)
 	    {
-	       for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
-		  out << ' ';
+	       if (Now == true)
+		  ioprintf(out,_("but %s is installed"),Ver.VerStr());
+	       else
+		  ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
 	    }
 	    else
-	       out << ' ' << End.DepType() << ": ";
-	    FirstOr = false;
-	    
-	    out << Start.TargetPkg().FullName(true);
-	 
-	    // Show a quick summary of the version requirements
-	    if (Start.TargetVer() != 0)
-	       out << " (" << Start.CompType() << " " << 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)
 	    {
-	       out << ' ';
-	       pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
-	       if (Now == true)
-		  Ver = Targ.CurrentVer();
-	       	    
-	       if (Ver.end() == false)
+	       if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
 	       {
-		  if (Now == true)
-		     ioprintf(out,_("but %s is installed"),Ver.VerStr());
+		  if (Targ->ProvidesList == 0)
+		     out << _("but it is not installable");
 		  else
-		     ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
-	       }	       
+		     out << _("but it is a virtual package");
+	       }
 	       else
-	       {
-		  if (Cache[Targ].CandidateVerIter(Cache).end() == true)
-		  {
-		     if (Targ->ProvidesList == 0)
-			out << _("but it is not installable");
-		     else
-			out << _("but it is a virtual package");
-		  }		  
-		  else
-		     out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
-	       }	       
+		  out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
 	    }
-	    
-	    if (Start != End)
-	       out << _(" or");
-	    out << endl;
-	    
-	    if (Start == End)
-	       break;
-	    ++Start;
-	 }	 
-      }	    
-   }   
+	 }
+
+	 if (Start != End)
+	    out << _(" or");
+	 out << endl;
+
+	 if (Start == End)
+	    break;
+	 ++Start;
+      }
+   }
+}
+void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
+{
+   if (Cache->BrokenCount() == 0)
+      return;
+
+   out << _("The following packages have unmet dependencies:") << endl;
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator const I(Cache,Cache.List[J]);
+      ShowBrokenPackage(out, &Cache, I, Now);
+   }
+}
+void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
+{
+   if (Cache->BrokenCount() == 0)
+      return;
+
+   out << _("The following packages have unmet dependencies:") << endl;
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
+      ShowBrokenPackage(out, &Cache, Pkg, Now);
 }
 									/*}}}*/
 // ShowNew - Show packages to newly install				/*{{{*/