]> git.saurik.com Git - apt.git/blob - apt-pkg/contrib/progress.cc
give a descriptive error for pipe tries with 'false'
[apt.git] / apt-pkg / contrib / progress.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: progress.cc,v 1.12 2003/01/11 07:17:04 jgg Exp $
4 /* ######################################################################
5
6 OpProgress - Operation Progress
7
8 ##################################################################### */
9 /*}}}*/
10 // Include Files /*{{{*/
11 #include <config.h>
12
13 #include <apt-pkg/progress.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/configuration.h>
16
17 #include <sys/time.h>
18 #include <string>
19 #include <iostream>
20 #include <stdio.h>
21 #include <cstring>
22
23 #include <apti18n.h>
24 /*}}}*/
25
26 using namespace std;
27
28 // OpProgress::OpProgress - Constructor /*{{{*/
29 // ---------------------------------------------------------------------
30 /* */
31 OpProgress::OpProgress() : Current(0), Total(0), Size(0), SubTotal(1),
32 LastPercent(0), Percent(0)
33 {
34 memset(&LastTime,0,sizeof(LastTime));
35 }
36 /*}}}*/
37 // OpProgress::Progress - Sub progress with no state change /*{{{*/
38 // ---------------------------------------------------------------------
39 /* Current is the Base Overall progress in units of Total. Cur is the sub
40 progress in units of SubTotal. Size is a scaling factor that says what
41 percent of Total SubTotal is. */
42 void OpProgress::Progress(unsigned long long Cur)
43 {
44 if (Total == 0 || Size == 0 || SubTotal == 0)
45 Percent = 0;
46 else
47 Percent = (Current + Cur/((float)SubTotal)*Size)*100.0/Total;
48 Update();
49 }
50 /*}}}*/
51 // OpProgress::OverallProgress - Set the overall progress /*{{{*/
52 // ---------------------------------------------------------------------
53 /* */
54 void OpProgress::OverallProgress(unsigned long long Current, unsigned long long Total,
55 unsigned long long Size,const string &Op)
56 {
57 this->Current = Current;
58 this->Total = Total;
59 this->Size = Size;
60 this->Op = Op;
61 SubOp = string();
62 if (Total == 0)
63 Percent = 0;
64 else
65 Percent = Current*100.0/Total;
66 Update();
67 }
68 /*}}}*/
69 // OpProgress::SubProgress - Set the sub progress state /*{{{*/
70 // ---------------------------------------------------------------------
71 /* */
72 void OpProgress::SubProgress(unsigned long long SubTotal,const string &Op,
73 float const Percent)
74 {
75 this->SubTotal = SubTotal;
76 if (Op.empty() == false)
77 SubOp = Op;
78 if (Total == 0 || Percent == 0)
79 this->Percent = 0;
80 else if (Percent != -1)
81 this->Percent = this->Current += (Size*Percent)/SubTotal;
82 else
83 this->Percent = Current*100.0/Total;
84 Update();
85 }
86 /*}}}*/
87 // OpProgress::CheckChange - See if the display should be updated /*{{{*/
88 // ---------------------------------------------------------------------
89 /* Progress calls are made so frequently that if every one resulted in
90 an update the display would be swamped and the system much slower.
91 This provides an upper bound on the update rate. */
92 bool OpProgress::CheckChange(float Interval)
93 {
94 // New major progress indication
95 if (Op != LastOp)
96 {
97 MajorChange = true;
98 LastOp = Op;
99 return true;
100 }
101 MajorChange = false;
102
103 if (SubOp != LastSubOp)
104 {
105 LastSubOp = SubOp;
106 return true;
107 }
108
109 if ((int)LastPercent == (int)Percent)
110 return false;
111
112 LastPercent = Percent;
113
114 if (Interval == 0)
115 return false;
116
117 // Check time delta
118 struct timeval Now;
119 gettimeofday(&Now,0);
120 double Diff = Now.tv_sec - LastTime.tv_sec + (Now.tv_usec - LastTime.tv_usec)/1000000.0;
121 if (Diff < Interval)
122 return false;
123 LastTime = Now;
124 return true;
125 }
126 /*}}}*/
127 // OpTextProgress::OpTextProgress - Constructor /*{{{*/
128 // ---------------------------------------------------------------------
129 /* */
130 OpTextProgress::OpTextProgress(Configuration &Config) :
131 NoUpdate(false), NoDisplay(false), LastLen(0)
132 {
133 if (Config.FindI("quiet",0) >= 1 || Config.FindB("quiet::NoUpdate", false) == true)
134 NoUpdate = true;
135 if (Config.FindI("quiet",0) >= 2 || Config.FindB("quiet::NoProgress", false) == true)
136 NoDisplay = true;
137 }
138 /*}}}*/
139 // OpTextProgress::Done - Clean up the display /*{{{*/
140 // ---------------------------------------------------------------------
141 /* */
142 void OpTextProgress::Done()
143 {
144 if (NoUpdate == false && OldOp.empty() == false)
145 {
146 char S[300];
147 if (_error->PendingError() == true)
148 snprintf(S,sizeof(S),_("%c%s... Error!"),'\r',OldOp.c_str());
149 else
150 snprintf(S,sizeof(S),_("%c%s... Done"),'\r',OldOp.c_str());
151 Write(S);
152 cout << endl;
153 OldOp = string();
154 }
155
156 if (NoUpdate == true && NoDisplay == false && OldOp.empty() == false)
157 {
158 OldOp = string();
159 cout << endl;
160 }
161 }
162 /*}}}*/
163 // OpTextProgress::Update - Simple text spinner /*{{{*/
164 // ---------------------------------------------------------------------
165 /* */
166 void OpTextProgress::Update()
167 {
168 if (CheckChange((NoUpdate == true?0:0.7)) == false)
169 return;
170
171 // No percent spinner
172 if (NoUpdate == true)
173 {
174 if (MajorChange == false)
175 return;
176 if (NoDisplay == false)
177 {
178 if (OldOp.empty() == false)
179 cout << endl;
180 OldOp = "a";
181 cout << Op << _("...") << flush;
182 }
183
184 return;
185 }
186
187 // Erase the old text and 'log' the event
188 char S[300];
189 if (MajorChange == true && OldOp.empty() == false)
190 {
191 snprintf(S,sizeof(S),"\r%s",OldOp.c_str());
192 Write(S);
193 cout << endl;
194 }
195
196 // Print the spinner
197 snprintf(S,sizeof(S),_("%c%s... %u%%"),'\r',Op.c_str(),(unsigned int)Percent);
198 Write(S);
199
200 OldOp = Op;
201 }
202 /*}}}*/
203 // OpTextProgress::Write - Write the progress string /*{{{*/
204 // ---------------------------------------------------------------------
205 /* This space fills the end to overwrite the previous text */
206 void OpTextProgress::Write(const char *S)
207 {
208 cout << S;
209 for (unsigned int I = strlen(S); I < LastLen; I++)
210 cout << ' ';
211 cout << '\r' << flush;
212 LastLen = strlen(S);
213 }
214 /*}}}*/