- More progress meter work. Broken in various entertaining ways at the
authorPanu Matilainen <pmatilai@turre.koti.laiskiainen.org>
Mon, 5 Mar 2007 21:39:29 +0000 (23:39 +0200)
committerPanu Matilainen <pmatilai@turre.koti.laiskiainen.org>
Mon, 5 Mar 2007 21:39:29 +0000 (23:39 +0200)
  moment
- Unbreak API by allowing DoInstall() to create "compatibility" progress
  meters. Compatibility inteded mostly for Synaptic, which has dirrrrrrrrrty
  hacks that break the pkgPackageManager class protections, invalidating
  our compat hacks. Oh well...

apt-pkg/contrib/progress.cc
apt-pkg/contrib/progress.h
apt-pkg/packagemanager.cc
apt-pkg/packagemanager.h
apt-pkg/rpm/rpmcallback.cc
apt-pkg/rpm/rpmpm.cc
apt-pkg/rpm/rpmpm.h
cmdline/apt-get.cc
cmdline/apt-shell.cc

index 8671078..a969720 100644 (file)
@@ -18,6 +18,7 @@
 #include <apti18n.h>
 
 #include <iostream>
+#include <iomanip>
 #include <stdio.h>
                                                                        /*}}}*/
 
@@ -110,8 +111,10 @@ bool OpProgress::CheckChange(float Interval)
    if (SubOp != LastSubOp)
    {
       LastSubOp = SubOp;
+      SubChange = true;
       return true;
    }
+   SubChange = false;
    
    if ((int)LastPercent == (int)Percent)
       return false;
@@ -219,82 +222,84 @@ void OpTextProgress::Write(const char *S)
 }
                                                                        /*}}}*/
 
-InstTextProgress::InstTextProgress(Configuration &Config) : 
-                               InstProgress(Config),
-                                       NoUpdate(false), NoDisplay(false), LastLen(0) 
+InstPercentProgress::InstPercentProgress(Configuration &Config) : 
+                               InstProgress(Config)
 {
 }
 
-void InstTextProgress::Done()
+void InstPercentProgress::Done()
 {
-   if (NoUpdate == false && OldOp.empty() == false)
-   {
-      char S[300];
-      if (_error->PendingError() == true)
-        snprintf(S,sizeof(S),_("%c%s... Error!"),'\r',OldOp.c_str());
-      else
-        snprintf(S,sizeof(S),_("%c%s... Done"),'\r',OldOp.c_str());
-      Write(S);
-      cout << endl;
-      OldOp = string();
-   }
-   
-   if (NoUpdate == true && NoDisplay == false && OldOp.empty() == false)
-   {
-      OldOp = string();
-      cout << endl;   
-   }   
+   Percent = 100;
+   Update();
 }
                                                                        /*}}}*/
-// OpTextProgress::Update - Simple text spinner                                /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void InstTextProgress::Update()
+void InstPercentProgress::Update()
 {
-   if (CheckChange((NoUpdate == true?0:0.7)) == false)
+   if (CheckChange(0.001) == false)
       return;
-   
-   // No percent spinner
-   if (NoUpdate == true)
-   {
-      if (MajorChange == false)
-        return;
-      if (NoDisplay == false)
-      {
-        if (OldOp.empty() == false)
-           cout << endl;
-        OldOp = "a";
-        cout << Op << "..." << flush;
-      }
-      
+
+   //cout << "major " << Op << " " << MajorChange << " new " << SubOp << " changed " << SubChange << endl << flush;
+   if (MajorChange == true)
       return;
+   if (SubChange == true) {
+      if (State == Preparing) {
+        cout << SubOp << endl << flush;
+      } else if (State == Installing) {
+        cout << (*PackageData)["name"] << "-";
+        cout << (*PackageData)["version"] << "-";
+        cout << (*PackageData)["release"];
+        cout << endl << flush;
+      }
+   } else if (State == Installing or State == Preparing) {
+      cout.setf(ios_base::showpoint);
+      cout.setf(ios_base::fixed, ios_base::floatfield);
+      cout << "%% " << setprecision(6) << Percent << endl << flush;
    }
+}
 
-   // Erase the old text and 'log' the event
-   char S[300];
-   if (MajorChange == true && OldOp.empty() == false)
-   {
-      snprintf(S,sizeof(S),"\r%s",OldOp.c_str());
-      Write(S);
-      cout << endl;
+void InstHashProgress::Update()
+{
+   if (CheckChange(0.001) == false)
+      return;
+
+   if (MajorChange == true) {
+      cout << endl << Op << flush;
+      return;
    }
-   
-   // Print the spinner
-   snprintf(S,sizeof(S),"\r%s... %s: %u%%",Op.c_str(),SubOp.c_str(), (unsigned int)Percent);
-   Write(S);
+   if (SubChange == true) {
+      cout << endl << flush;
+   }
+   string s;
+   if (State == Preparing) {
+      s = SubOp; 
+   } else {
+      s = (*PackageData)["name"] + "-" + 
+          (*PackageData)["version"] + "-" + 
+          (*PackageData)["release"]; 
+   }
+   cout << "\r";
+   cout.setf(ios_base::left);
+   cout << setw(25) << s << " ";
+   PrintHashes();
+}
 
-   OldOp = Op;
+void InstHashProgress::PrintHashes()
+{
+   int hashesTotal = 50;
+   int hashesNeeded = int(50 * Percent / 100);
+           
+   for (int i=0; i < hashesNeeded; i++ ) {
+      cout << "#";
+   }
+   cout << flush;
+   //cout << "need hashes " << hashesNeeded << " for " << Percent << endl << flush;
 }
-                                                                       /*}}}*/
-// OpTextProgress::Write - Write the progress string                   /*{{{*/
-// ---------------------------------------------------------------------
-/* This space fills the end to overwrite the previous text */
-void InstTextProgress::Write(const char *S)
+
+void InstHashProgress::Done()
 {
-   cout << S;
-   for (unsigned int I = strlen(S); I < LastLen; I++)
-      cout << ' ';
-   cout << '\r' << flush;
-   LastLen = strlen(S);
+   Percent = 100;
+   Update();
+   cout << endl;
 }
+
 // vim:sts=3:sw=3
index aad8d39..b07d742 100644 (file)
 #pragma interface "apt-pkg/progress.h"
 #endif 
 
+#include <map>
 #include <string>
 #include <sys/time.h>
 
 using std::string;
+using std::map;
 
 class Configuration;
 class OpProgress
 {
-   unsigned long Current;
-   unsigned long Total;
-   unsigned long Size;
-   unsigned long SubTotal;
+   off_t Current;
+   off_t Total;
+   off_t Size;
+   off_t SubTotal;
    float LastPercent;
    
    // Change reduction code
@@ -51,6 +53,7 @@ class OpProgress
    float Percent;
    
    bool MajorChange;
+   bool SubChange;
    
    bool CheckChange(float Interval = 0.7);                 
    virtual void Update() {};
@@ -89,30 +92,50 @@ class OpTextProgress : public OpProgress
    virtual ~OpTextProgress() {Done();};
 };
 
+
 class InstProgress : public OpProgress
+{
+   public:
+   enum InstallStates { Preparing, Installing, Repackaging, Removing };
+
+   void SetState(enum InstallStates St) {State = St;};
+   void SetPackageData(map<string,string> *PkgData) {PackageData=PkgData;};
+   InstProgress(Configuration &Config) : OpProgress(), PackageData(NULL) {};
+   virtual ~InstProgress() {};
+
+   protected:
+   map<string,string> *PackageData;
+   enum InstallStates State;
+};
+
+// Progress class that emulates "rpm -Uv --percent" output for Synaptic
+// compatibility 
+class InstPercentProgress : public InstProgress
 {
    protected:
+   virtual void Update();
 
    public:
-   InstProgress(Configuration &Config) : OpProgress() {};
-   virtual ~InstProgress() {};
+   virtual void Done();
+
+   InstPercentProgress(Configuration &Config);
+   virtual ~InstPercentProgress() {Done();};
 };
 
-class InstTextProgress : public InstProgress
+// Progress class similar to rpm -Uvh but with erasure callbacks and whatnot
+// TODO: actually implement it ;)
+class InstHashProgress : public InstProgress
 {
    protected:
-   string OldOp;
-   bool NoUpdate;
-   bool NoDisplay;
-   unsigned long LastLen;
+
    virtual void Update();
-   void Write(const char *S);
+   void PrintHashes();
 
    public:
    virtual void Done();
 
-   InstTextProgress(Configuration &Config);
-   virtual ~InstTextProgress() {Done();};
+   InstHashProgress(Configuration &Config) : InstProgress(Config) {};
+   virtual ~InstHashProgress() {Done();};
 };
 #endif
 
index 83b80ca..49dbba0 100644 (file)
@@ -664,13 +664,27 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
 // ---------------------------------------------------------------------
 /* This uses the filenames in FileNames and the information in the
    DepCache to perform the installation of packages.*/
-pkgPackageManager::OrderResult pkgPackageManager::DoInstall(InstProgress &Prog)
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall(InstProgress *Prog)
 {
+   Progress = Prog;
    OrderResult Res = OrderInstall();
    if (Res != Failed)
-      if (Go(Prog) == false)
+      if (Go() == false)
         return Failed;
    return Res;
 }
                                                                        /*}}}*/
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall()
+{
+   InstProgress *Prog;
+   pkgPackageManager::OrderResult res;
+   if (_config->FindB("RPM::Interactive",true)) {
+      Prog = new InstHashProgress(*_config);
+   } else {
+      Prog = new InstPercentProgress(*_config);
+   }
+   res = DoInstall(Prog);
+   delete Prog;
+   return res; 
+}
 // vim:sts=3:sw=3
index 42128a6..77201ac 100644 (file)
@@ -48,6 +48,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    string *FileNames;
    pkgDepCache &Cache;
    pkgOrderList *List;
+   InstProgress *Progress;
    bool Debug;
          
    bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
@@ -69,7 +70,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual bool Install(PkgIterator /*Pkg*/,string /*File*/) {return false;};
    virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
-   virtual bool Go(InstProgress &Prog) {return true;};
+   virtual bool Go() {return true;};
    virtual void Reset() {};
    
    public:
@@ -77,7 +78,8 @@ class pkgPackageManager : protected pkgCache::Namespace
    // Main action members
    bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
                    pkgRecords *Recs);
-   OrderResult DoInstall(InstProgress &Prog);
+   OrderResult DoInstall(InstProgress *Prog);
+   OrderResult DoInstall();
    bool FixMissing();
    
    pkgPackageManager(pkgDepCache *Cache);
index 08ff862..e234154 100644 (file)
@@ -1,4 +1,4 @@
-
+#include <map>
 #include <stdio.h>
 #include <rpm/rpmlib.h>
 #include <apti18n.h>
@@ -9,9 +9,26 @@
 #include <iostream>
 using namespace std;
 
-static int progressCurrent = 0;
-static int progressTotal = 0;
-int packagesTotal = 0;
+static char *copyTags[] = {"name", 
+                          "version", 
+                          "release", 
+                          "arch", 
+                          "summary", 
+                          NULL};
+
+static void getPackageData(const Header h, map<string,string> &Data)
+{
+   char **Tag = &copyTags[0];
+   char rTag[20];
+   Data.clear();
+   for (Tag = &copyTags[0]; *Tag != NULL; *Tag++) {
+      sprintf(rTag, "%{%s}", *Tag);
+      char *s = headerSprintf(h, rTag, rpmTagTable, rpmHeaderFormats, NULL);
+      Data[*Tag] = s;
+      free(s);
+   }
+
+}
 
 #if RPM_VERSION < 0x040000
 void * rpmCallback(const Header h,
@@ -29,12 +46,13 @@ void * rpmCallback(const void * arg,
 #endif
 
    char * s;
-   OpProgress *Prog = (OpProgress*)data;
+   InstProgress *Prog = (InstProgress*)data;
    void * rc = NULL;
    const char * filename = (const char *) pkgKey;
    static FD_t fd = NULL;
    static rpmCallbackType state;
    static bool repackage;
+   static map<string,string> Data;
 
    switch (what) {
    case RPMCALLBACK_INST_OPEN_FILE:
@@ -57,49 +75,46 @@ void * rpmCallback(const void * arg,
    case RPMCALLBACK_INST_START:
       if (state != what && repackage == false) {
         state = what;
-        Prog->Progress(100);
         Prog->OverallProgress(0,1,1, "Installing");
+        Prog->SetState(InstProgress::Installing);
       }
 
-      s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}",
-                                 rpmTagTable, rpmHeaderFormats, NULL);
-      Prog->SubProgress(100, s);
+      getPackageData(h, Data);
+      Prog->SubProgress(total, Data["name"]);
+      Prog->Progress(amount);
       break;
 
    case RPMCALLBACK_TRANS_PROGRESS:
+      //cout << "RPMCALLBACK_TRANS_PROGRESS " << amount << " " << total << endl << flush;
    case RPMCALLBACK_INST_PROGRESS:
-      Prog->Progress((int) (total ? ((((float) amount) / total) * 100): 100.0));
+      //cout << "RPMCALLBACK_INST_PROGRESS " << amount << " " << total << endl << flush;
+      Prog->Progress(amount);
       break;
 
    case RPMCALLBACK_TRANS_START:
+      //cout << "RPMCALLBACK_TRANS_START " << amount << " " << total << endl << flush;
       state = what;
       repackage = false;
-      progressTotal = 1;
-      progressCurrent = 0;
-      Prog->OverallProgress(0,100,1, "Preparing");
+      Prog->SetState(InstProgress::Preparing);
+      Prog->SubProgress(total, "Preparing");
+      Prog->SetPackageData(&Data);
    break;
 
    case RPMCALLBACK_TRANS_STOP:
-      Prog->Progress(100);
       Prog->Done();
-      progressTotal = packagesTotal;
-      progressCurrent = 0;
       break;
 
    case RPMCALLBACK_REPACKAGE_START:
-      progressCurrent = 0;
       repackage = true;
       Prog->OverallProgress(0,1,1, "Repackaging");
+      Prog->SetState(InstProgress::Repackaging);
       break;
 
    case RPMCALLBACK_REPACKAGE_PROGRESS:
-      Prog->Progress(100);
+      Prog->Progress(amount);
       break;
 
    case RPMCALLBACK_REPACKAGE_STOP:
-      progressTotal = total;
-      progressCurrent = total;
-      progressTotal = packagesTotal;
       repackage = false;
       break;
 
@@ -107,18 +122,25 @@ void * rpmCallback(const void * arg,
       break;
 
    case RPMCALLBACK_UNINST_START:
+      if (h == NULL) {
+        cout << "uninst start, header null ;(" << endl;
+        break;
+      }
       if (state != what) {
         state = what;
+        Prog->SetState(InstProgress::Removing);
         Prog->OverallProgress(0,1,1, "Removing");
       }
+      getPackageData(h, Data);
+      Prog->SubProgress(total, Data["name"]);
+      Prog->Progress(total);
       break;
 
    case RPMCALLBACK_UNINST_STOP:
+      Prog->Progress(total);
       if (h == NULL)
         break;
-      s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}",
-                                 rpmTagTable, rpmHeaderFormats, NULL);
-      Prog->SubProgress(1, s);
+      getPackageData(h, Data);
       break;
    default: // Fall through
       break;
index 91eeb30..f7ab343 100644 (file)
@@ -238,7 +238,7 @@ bool pkgRPMPM::RunScriptsWithPkgs(const char *Cnf)
 // RPMPM::Go - Run the sequence                                                /*{{{*/
 // ---------------------------------------------------------------------
 /* This globs the operations and calls rpm */
-bool pkgRPMPM::Go(InstProgress &Prog)
+bool pkgRPMPM::Go()
 {
    if (List.empty() == true)
       return true;
@@ -341,7 +341,7 @@ bool pkgRPMPM::Go(InstProgress &Prog)
    }
 #endif
 
-   if (Process(Prog, install, upgrade, uninstall) == false)
+   if (Process(install, upgrade, uninstall) == false)
       Ret = false;
 
 #ifdef APT_WITH_LUA
@@ -640,10 +640,9 @@ bool pkgRPMExtPM::ExecRPM(Item::RPMOps op, vector<const char*> &files)
    return true;
 }
 
-bool pkgRPMExtPM::Process(InstProgress &Prog, 
-                      vector<const char*> &install, 
-                      vector<const char*> &upgrade,
-                      vector<const char*> &uninstall)
+bool pkgRPMExtPM::Process(vector<const char*> &install, 
+                         vector<const char*> &upgrade,
+                         vector<const char*> &uninstall)
 {
    if (uninstall.empty() == false)
        ExecRPM(Item::RPMErase, uninstall);
@@ -745,8 +744,7 @@ bool pkgRPMLibPM::AddToTransaction(Item::RPMOps op, vector<const char*> &files)
    return true;
 }
 
-bool pkgRPMLibPM::Process(InstProgress &Prog,
-                         vector<const char*> &install, 
+bool pkgRPMLibPM::Process(vector<const char*> &install, 
                          vector<const char*> &upgrade,
                          vector<const char*> &uninstall)
 {
@@ -832,7 +830,8 @@ bool pkgRPMLibPM::Process(InstProgress &Prog,
    if (upgrade.empty() == false)
        AddToTransaction(Item::RPMUpgrade, upgrade);
 
-   packagesTotal = 0;
+   // XXX temp stuff..
+   int packagesTotal = 0;
    // Figure out exactly how many rpm operations we're going to process,
    // repackages and all.
    int repackage = (tsFlags & RPMTRANS_FLAG_REPACKAGE) ? 1 : 0;
@@ -891,16 +890,16 @@ bool pkgRPMLibPM::Process(InstProgress &Prog,
       goto exit;
    }
 
-   Prog.OverallProgress(0, 1, 1, "Committing changes...");
+   Progress->OverallProgress(0, 1, 1, "Committing changes...");
 #if RPM_VERSION >= 0x040100
    probFilter |= rpmtsFilterFlags(TS);
    rpmtsSetFlags(TS, (rpmtransFlags)(rpmtsFlags(TS) | tsFlags));
    rpmtsClean(TS);
-   rc = rpmtsSetNotifyCallback(TS, rpmCallback, &Prog);
+   rc = rpmtsSetNotifyCallback(TS, rpmCallback, Progress);
    rc = rpmtsRun(TS, NULL, (rpmprobFilterFlags)probFilter);
    probs = rpmtsProblems(TS);
 #else
-   rc = rpmRunTransactions(TS, rpmpmShowProgress, (void *)notifyFlags, NULL,
+   rc = rpmRunTransactions(TS, rpmCallback, Progress, NULL,
                            &probs, (rpmtransFlags)tsFlags,
                           (rpmprobFilterFlags)probFilter);
 #endif
index 6206444..2b58925 100644 (file)
@@ -56,12 +56,11 @@ class pkgRPMPM : public pkgPackageManager
    virtual bool Configure(PkgIterator Pkg);
    virtual bool Remove(PkgIterator Pkg,bool Purge = false);
     
-   virtual bool Process(InstProgress &Prog,
-               vector<const char*> &install,
-               vector<const char*> &upgrade,
-               vector<const char*> &uninstall) {return false;};
+   virtual bool Process(vector<const char*> &install,
+                       vector<const char*> &upgrade,
+                       vector<const char*> &uninstall) {return false;};
    
-   virtual bool Go(InstProgress &Prog);
+   virtual bool Go();
    virtual void Reset();
    
    public:
@@ -74,10 +73,9 @@ class pkgRPMExtPM : public pkgRPMPM
 {
    protected:
    bool ExecRPM(Item::RPMOps op, vector<const char*> &files);
-   virtual bool Process(InstProgress &Prog,
-               vector<const char*> &install,
-               vector<const char*> &upgrade,
-               vector<const char*> &uninstall);
+   virtual bool Process(vector<const char*> &install,
+                       vector<const char*> &upgrade,
+                       vector<const char*> &uninstall);
 
    public:
    pkgRPMExtPM(pkgDepCache *Cache);
@@ -96,10 +94,9 @@ class pkgRPMLibPM : public pkgRPMPM
 
    bool ParseRpmOpts(const char *Cnf, int *tsFlags, int *probFilter);
    bool AddToTransaction(Item::RPMOps op, vector<const char*> &files);
-   virtual bool Process(InstProgress &Prog,
-               vector<const char*> &install,
-               vector<const char*> &upgrade,
-               vector<const char*> &uninstall);
+   virtual bool Process(vector<const char*> &install,
+                       vector<const char*> &upgrade,
+                       vector<const char*> &uninstall);
 
    public:
 
index 91c18e9..7eaa3ec 100644 (file)
@@ -271,8 +271,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    if (_config->FindB("APT::Get::Simulate") == true)
    {
       pkgSimulate PM(Cache);
-      InstTextProgress Prog(*_config);
-      pkgPackageManager::OrderResult Res = PM.DoInstall(Prog);
+      pkgPackageManager::OrderResult Res = PM.DoInstall();
       if (Res == pkgPackageManager::Failed)
         return false;
       if (Res != pkgPackageManager::Completed)
@@ -514,8 +513,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
            _config->Set("RPM::Install-Options::", "--nodeps");
         }
         _system->UnLock();
-        InstTextProgress Prog(*_config);
-        pkgPackageManager::OrderResult Res = PM->DoInstall(Prog);
+        pkgPackageManager::OrderResult Res = PM->DoInstall();
         if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
         {
            if (Transient == false)
index d4ad8fe..dfcdb2d 100644 (file)
@@ -333,8 +333,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    if (_config->FindB("APT::Get::Simulate") == true)
    {
       pkgSimulate PM(Cache);
-      InstTextProgress Prog(*_config);
-      pkgPackageManager::OrderResult Res = PM.DoInstall(Prog);
+      pkgPackageManager::OrderResult Res = PM.DoInstall();
       if (Res == pkgPackageManager::Failed)
         return false;
       if (Res != pkgPackageManager::Completed)
@@ -575,8 +574,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
            _config->Set("RPM::Install-Options::", "--nodeps");
         }
         _system->UnLock();
-        InstTextProgress Prog(*_config);
-        pkgPackageManager::OrderResult Res = PM->DoInstall(Prog);
+        pkgPackageManager::OrderResult Res = PM->DoInstall();
         if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
         {
            if (Transient == false)