summaryrefslogtreecommitdiffstats
path: root/apt-pkg/contrib/progress.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib/progress.cc')
-rw-r--r--apt-pkg/contrib/progress.cc221
1 files changed, 221 insertions, 0 deletions
diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc
new file mode 100644
index 0000000..806bd47
--- /dev/null
+++ b/apt-pkg/contrib/progress.cc
@@ -0,0 +1,221 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+/* ######################################################################
+
+ OpProgress - Operation Progress
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include <config.h>
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/progress.h>
+
+#include <cmath>
+#include <chrono>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <stdio.h>
+#include <sys/time.h>
+
+#include <apti18n.h>
+ /*}}}*/
+
+using namespace std;
+
+// OpProgress::OpProgress - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+OpProgress::OpProgress() : Current(0), Total(0), Size(0), SubTotal(1),
+ LastPercent(0), Percent(0)
+{
+ memset(&LastTime,0,sizeof(LastTime));
+}
+ /*}}}*/
+// OpProgress::Progress - Sub progress with no state change /*{{{*/
+// ---------------------------------------------------------------------
+/* Current is the Base Overall progress in units of Total. Cur is the sub
+ progress in units of SubTotal. Size is a scaling factor that says what
+ percent of Total SubTotal is. */
+void OpProgress::Progress(unsigned long long Cur)
+{
+ if (Total == 0 || Size == 0 || SubTotal == 0)
+ Percent = 0;
+ else
+ Percent = (Current + Cur/((double)SubTotal)*Size)*100.0/Total;
+ Update();
+}
+ /*}}}*/
+// OpProgress::OverallProgress - Set the overall progress /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void OpProgress::OverallProgress(unsigned long long Current, unsigned long long Total,
+ unsigned long long Size,const string &Op)
+{
+ this->Current = Current;
+ this->Total = Total;
+ this->Size = Size;
+ this->Op = Op;
+ SubOp = string();
+ if (Total == 0)
+ Percent = 0;
+ else
+ Percent = Current*100.0/Total;
+ Update();
+}
+ /*}}}*/
+// OpProgress::SubProgress - Set the sub progress state /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void OpProgress::SubProgress(unsigned long long SubTotal,const string &Op,
+ float const Percent)
+{
+ this->SubTotal = SubTotal;
+ if (Op.empty() == false)
+ SubOp = Op;
+ if (Total == 0 || Percent == 0)
+ this->Percent = 0;
+ else if (Percent != -1)
+ this->Percent = this->Current += (Size*Percent)/SubTotal;
+ else
+ this->Percent = Current*100.0/Total;
+ Update();
+}
+ /*}}}*/
+// OpProgress::CheckChange - See if the display should be updated /*{{{*/
+// ---------------------------------------------------------------------
+/* Progress calls are made so frequently that if every one resulted in
+ an update the display would be swamped and the system much slower.
+ This provides an upper bound on the update rate. */
+bool OpProgress::CheckChange(float Interval)
+{
+ // New major progress indication
+ if (Op != LastOp)
+ {
+ MajorChange = true;
+ LastOp = Op;
+ return true;
+ }
+ MajorChange = false;
+
+ if (SubOp != LastSubOp)
+ {
+ LastSubOp = SubOp;
+ return true;
+ }
+
+ if (std::lround(LastPercent) == std::lround(Percent))
+ return false;
+
+ LastPercent = Percent;
+
+ if (Interval == 0)
+ return false;
+
+ // Check time delta
+ auto const Now = std::chrono::steady_clock::now().time_since_epoch();
+ auto const Now_sec = std::chrono::duration_cast<std::chrono::seconds>(Now);
+ auto const Now_usec = std::chrono::duration_cast<std::chrono::microseconds>(Now - Now_sec);
+ struct timeval NowTime = { Now_sec.count(), Now_usec.count() };
+
+ std::chrono::duration<decltype(Interval)> Delta =
+ std::chrono::seconds(NowTime.tv_sec - LastTime.tv_sec) +
+ std::chrono::microseconds(NowTime.tv_sec - LastTime.tv_usec);
+
+ if (Delta.count() < Interval)
+ return false;
+ LastTime = NowTime;
+ return true;
+}
+ /*}}}*/
+// OpTextProgress::OpTextProgress - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+OpTextProgress::OpTextProgress(Configuration &Config) :
+ NoUpdate(false), NoDisplay(false), LastLen(0)
+{
+ if (Config.FindI("quiet",0) >= 1 || Config.FindB("quiet::NoUpdate", false) == true)
+ NoUpdate = true;
+ if (Config.FindI("quiet",0) >= 2 || Config.FindB("quiet::NoProgress", false) == true)
+ NoDisplay = true;
+}
+ /*}}}*/
+// OpTextProgress::Done - Clean up the display /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void OpTextProgress::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;
+ }
+}
+ /*}}}*/
+// OpTextProgress::Update - Simple text spinner /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void OpTextProgress::Update()
+{
+ if (CheckChange((NoUpdate == true?0:0.7)) == 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;
+ }
+
+ return;
+ }
+
+ // 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;
+ }
+
+ // Print the spinner
+ snprintf(S,sizeof(S),_("%c%s... %u%%"),'\r',Op.c_str(),(unsigned int)Percent);
+ Write(S);
+
+ OldOp = Op;
+}
+ /*}}}*/
+// OpTextProgress::Write - Write the progress string /*{{{*/
+// ---------------------------------------------------------------------
+/* This space fills the end to overwrite the previous text */
+void OpTextProgress::Write(const char *S)
+{
+ cout << S;
+ for (unsigned int I = strlen(S); I < LastLen; I++)
+ cout << ' ';
+ cout << '\r' << flush;
+ LastLen = strlen(S);
+}
+ /*}}}*/