]>
git.saurik.com Git - apt.git/blob - apt-private/acqprogress.cc
1 // -*- mode: cpp; mode: fold -*-
3 /* ######################################################################
5 Acquire Progress - Command line progress meter
7 ##################################################################### */
9 // Include files /*{{{*/
12 #include <apt-pkg/acquire.h>
13 #include <apt-pkg/acquire-item.h>
14 #include <apt-pkg/acquire-worker.h>
15 #include <apt-pkg/configuration.h>
16 #include <apt-pkg/strutl.h>
17 #include <apt-pkg/error.h>
19 #include <apt-private/acqprogress.h>
31 // AcqTextStatus::AcqTextStatus - Constructor /*{{{*/
32 // ---------------------------------------------------------------------
34 AcqTextStatus::AcqTextStatus(std::ostream
&out
, unsigned int &ScreenWidth
,unsigned int const Quiet
) :
35 pkgAcquireStatus(), out(out
), ScreenWidth(ScreenWidth
), LastLineLength(0), ID(0), Quiet(Quiet
)
37 // testcases use it to disable pulses without disabling other user messages
38 if (Quiet
== 0 && _config
->FindB("quiet::NoUpdate", false) == true)
42 // AcqTextStatus::Start - Downloading has started /*{{{*/
43 // ---------------------------------------------------------------------
45 void AcqTextStatus::Start()
47 pkgAcquireStatus::Start();
52 void AcqTextStatus::AssignItemID(pkgAcquire::ItemDesc
&Itm
) /*{{{*/
54 /* In theory calling it from Fetch() would be enough, but to be
55 safe we call it from IMSHit and Fail as well.
56 Also, an Item can pass through multiple stages, so ensure
57 that it keeps the same number */
58 if (Itm
.Owner
->ID
== 0)
62 // AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/
63 // ---------------------------------------------------------------------
65 void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc
&Itm
)
73 // TRANSLATOR: Very short word to be displayed before unchanged files in 'apt-get update'
74 ioprintf(out
, _("Hit:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
79 // AcqTextStatus::Fetch - An item has started to download /*{{{*/
80 // ---------------------------------------------------------------------
81 /* This prints out the short description and the expected size */
82 void AcqTextStatus::Fetch(pkgAcquire::ItemDesc
&Itm
)
85 if (Itm
.Owner
->Complete
== true)
94 // TRANSLATOR: Very short word to be displayed for files processed in 'apt-get update'
95 // Potentially replaced later by "Hit:", "Ign:" or "Err:" if something (bad) happens
96 ioprintf(out
, _("Get:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
97 if (Itm
.Owner
->FileSize
!= 0)
98 out
<< " [" << SizeToStr(Itm
.Owner
->FileSize
) << "B]";
102 // AcqTextStatus::Done - Completed a download /*{{{*/
103 // ---------------------------------------------------------------------
104 /* We don't display anything... */
105 void AcqTextStatus::Done(pkgAcquire::ItemDesc
&Itm
)
111 // AcqTextStatus::Fail - Called when an item fails to download /*{{{*/
112 // ---------------------------------------------------------------------
113 /* We print out the error text */
114 void AcqTextStatus::Fail(pkgAcquire::ItemDesc
&Itm
)
119 // Ignore certain kinds of transient failures (bad code)
120 if (Itm
.Owner
->Status
== pkgAcquire::Item::StatIdle
)
126 if (Itm
.Owner
->Status
== pkgAcquire::Item::StatDone
)
128 // TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
129 // which failed to download, but the error is ignored (compare "Err:")
130 ioprintf(out
, _("Ign:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
131 if (Itm
.Owner
->ErrorText
.empty() == false &&
132 _config
->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true)
133 out
<< std::endl
<< " " << Itm
.Owner
->ErrorText
;
138 // TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
139 // which failed to download and the error is critical (compare "Ign:")
140 ioprintf(out
, _("Err:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
141 out
<< std::endl
<< " " << Itm
.Owner
->ErrorText
<< std::endl
;
147 // AcqTextStatus::Stop - Finished downloading /*{{{*/
148 // ---------------------------------------------------------------------
149 /* This prints out the bytes downloaded and the overall average line
151 void AcqTextStatus::Stop()
153 pkgAcquireStatus::Stop();
159 if (_config
->FindB("quiet::NoStatistic", false) == true)
162 if (FetchedBytes
!= 0 && _error
->PendingError() == false)
163 ioprintf(out
,_("Fetched %sB in %s (%sB/s)\n"),
164 SizeToStr(FetchedBytes
).c_str(),
165 TimeToStr(ElapsedTime
).c_str(),
166 SizeToStr(CurrentCPS
).c_str());
169 // AcqTextStatus::Pulse - Regular event pulse /*{{{*/
170 // ---------------------------------------------------------------------
171 /* This draws the current progress. Each line has an overall percent
172 meter and a per active item status meter along with an overall
173 bandwidth and ETA indicator. */
174 bool AcqTextStatus::Pulse(pkgAcquire
*Owner
)
176 pkgAcquireStatus::Pulse(Owner
);
181 enum {Long
= 0,Medium
,Short
} Mode
= Medium
;
186 for (pkgAcquire::Worker
*I
= Owner
->WorkersBegin(); I
!= 0;
187 I
= Owner
->WorkerStep(I
))
189 // There is no item running
190 if (I
->CurrentItem
== 0)
192 if (I
->Status
.empty() == false)
193 S
<< " [" << I
->Status
<< "]";
198 // Add in the short description
200 if (I
->CurrentItem
->Owner
->ID
!= 0)
201 S
<< I
->CurrentItem
->Owner
->ID
<< " ";
202 S
<< I
->CurrentItem
->ShortDesc
;
204 // Show the short mode string
205 if (I
->CurrentItem
->Owner
->ActiveSubprocess
.empty() == false)
206 S
<< " " << I
->CurrentItem
->Owner
->ActiveSubprocess
;
208 // Add the current progress
210 S
<< " " << I
->CurrentSize
;
213 if (Mode
== Medium
|| I
->TotalSize
== 0)
214 S
<< " " << SizeToStr(I
->CurrentSize
) << "B";
217 // Add the total size and percent
218 if (I
->TotalSize
> 0 && I
->CurrentItem
->Owner
->Complete
== false)
221 ioprintf(S
, " %.0f%%", (I
->CurrentSize
*100.0)/I
->TotalSize
);
223 ioprintf(S
, "/%sB %.0f%%", SizeToStr(I
->TotalSize
).c_str(),
224 (I
->CurrentSize
*100.0)/I
->TotalSize
);
229 // Show at least something
232 if (Line
.empty() == true)
233 Line
= _(" [Working]");
235 // Put in the percent done
238 ioprintf(S
, "%.0f%%", Percent
);
244 /* Put in the ETA and cps meter, block off signals to prevent strangeness
246 sigset_t Sigs
,OldSigs
;
248 sigaddset(&Sigs
,SIGWINCH
);
249 sigprocmask(SIG_BLOCK
,&Sigs
,&OldSigs
);
253 unsigned long long ETA
= (TotalBytes
- CurrentBytes
)/CurrentCPS
;
254 std::string Tmp
= " " + SizeToStr(CurrentCPS
) + "B/s " + TimeToStr(ETA
);
255 size_t alignment
= Line
.length() + Tmp
.length();
256 if (alignment
< ScreenWidth
)
258 alignment
= ScreenWidth
- alignment
;
259 for (size_t i
= 0; i
< alignment
; ++i
)
264 if (Line
.length() > ScreenWidth
)
265 Line
.erase(ScreenWidth
);
266 sigprocmask(SIG_SETMASK
,&OldSigs
,0);
268 // Draw the current status
269 if (_config
->FindB("Apt::Color", false) == true)
270 out
<< _config
->Find("APT::Color::Yellow");
271 if (LastLineLength
> Line
.length())
275 out
<< Line
<< std::flush
;
276 if (_config
->FindB("Apt::Color", false) == true)
277 out
<< _config
->Find("APT::Color::Neutral") << std::flush
;
279 LastLineLength
= Line
.length();
285 // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/
286 // ---------------------------------------------------------------------
287 /* Prompt for a media swap */
288 bool AcqTextStatus::MediaChange(std::string Media
, std::string Drive
)
290 // If we do not output on a terminal and one of the options to avoid user
291 // interaction is given, we assume that no user is present who could react
292 // on your media change request
293 if (isatty(STDOUT_FILENO
) != 1 && Quiet
>= 2 &&
294 (_config
->FindB("APT::Get::Assume-Yes",false) == true ||
295 _config
->FindB("APT::Get::Force-Yes",false) == true ||
296 _config
->FindB("APT::Get::Trivial-Only",false) == true))
301 ioprintf(out
,_("Media change: please insert the disc labeled\n"
303 "in the drive '%s' and press enter\n"),
304 Media
.c_str(),Drive
.c_str());
308 while (C
!= '\n' && C
!= '\r')
310 int len
= read(STDIN_FILENO
,&C
,1);
311 if(C
== 'c' || len
<= 0)
320 void AcqTextStatus::clearLastLine() { /*{{{*/
321 if (Quiet
> 0 || LastLineLength
== 0)
324 // do not try to clear more than the (now smaller) screen
325 if (LastLineLength
> ScreenWidth
)
326 LastLineLength
= ScreenWidth
;
329 for (size_t i
= 0; i
< LastLineLength
; ++i
)
331 out
<< '\r' << std::flush
;