]>
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
)
122 if (Itm
.Owner
->Status
== pkgAcquire::Item::StatDone
|| Itm
.Owner
->Status
== pkgAcquire::Item::StatIdle
)
124 // TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
125 // which failed to download, but the error is ignored (compare "Err:")
126 ioprintf(out
, _("Ign:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
127 if (Itm
.Owner
->ErrorText
.empty() == false &&
128 _config
->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true)
129 out
<< std::endl
<< " " << Itm
.Owner
->ErrorText
;
134 // TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
135 // which failed to download and the error is critical (compare "Ign:")
136 ioprintf(out
, _("Err:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
137 out
<< std::endl
<< " " << Itm
.Owner
->ErrorText
<< std::endl
;
143 // AcqTextStatus::Stop - Finished downloading /*{{{*/
144 // ---------------------------------------------------------------------
145 /* This prints out the bytes downloaded and the overall average line
147 void AcqTextStatus::Stop()
149 pkgAcquireStatus::Stop();
155 if (_config
->FindB("quiet::NoStatistic", false) == true)
158 if (FetchedBytes
!= 0 && _error
->PendingError() == false)
159 ioprintf(out
,_("Fetched %sB in %s (%sB/s)\n"),
160 SizeToStr(FetchedBytes
).c_str(),
161 TimeToStr(ElapsedTime
).c_str(),
162 SizeToStr(CurrentCPS
).c_str());
165 // AcqTextStatus::Pulse - Regular event pulse /*{{{*/
166 // ---------------------------------------------------------------------
167 /* This draws the current progress. Each line has an overall percent
168 meter and a per active item status meter along with an overall
169 bandwidth and ETA indicator. */
170 bool AcqTextStatus::Pulse(pkgAcquire
*Owner
)
172 pkgAcquireStatus::Pulse(Owner
);
177 enum {Long
= 0,Medium
,Short
} Mode
= Medium
;
182 for (pkgAcquire::Worker
*I
= Owner
->WorkersBegin(); I
!= 0;
183 I
= Owner
->WorkerStep(I
))
185 // There is no item running
186 if (I
->CurrentItem
== 0)
188 if (I
->Status
.empty() == false)
189 S
<< " [" << I
->Status
<< "]";
194 // Add in the short description
196 if (I
->CurrentItem
->Owner
->ID
!= 0)
197 S
<< I
->CurrentItem
->Owner
->ID
<< " ";
198 S
<< I
->CurrentItem
->ShortDesc
;
200 // Show the short mode string
201 if (I
->CurrentItem
->Owner
->ActiveSubprocess
.empty() == false)
202 S
<< " " << I
->CurrentItem
->Owner
->ActiveSubprocess
;
204 // Add the current progress
206 S
<< " " << I
->CurrentSize
;
209 if (Mode
== Medium
|| I
->TotalSize
== 0)
210 S
<< " " << SizeToStr(I
->CurrentSize
) << "B";
213 // Add the total size and percent
214 if (I
->TotalSize
> 0 && I
->CurrentItem
->Owner
->Complete
== false)
217 ioprintf(S
, " %.0f%%", (I
->CurrentSize
*100.0)/I
->TotalSize
);
219 ioprintf(S
, "/%sB %.0f%%", SizeToStr(I
->TotalSize
).c_str(),
220 (I
->CurrentSize
*100.0)/I
->TotalSize
);
225 // Show at least something
228 if (Line
.empty() == true)
229 Line
= _(" [Working]");
231 // Put in the percent done
234 ioprintf(S
, "%.0f%%", Percent
);
240 /* Put in the ETA and cps meter, block off signals to prevent strangeness
242 sigset_t Sigs
,OldSigs
;
244 sigaddset(&Sigs
,SIGWINCH
);
245 sigprocmask(SIG_BLOCK
,&Sigs
,&OldSigs
);
249 unsigned long long ETA
= (TotalBytes
- CurrentBytes
)/CurrentCPS
;
250 std::string Tmp
= " " + SizeToStr(CurrentCPS
) + "B/s " + TimeToStr(ETA
);
251 size_t alignment
= Line
.length() + Tmp
.length();
252 if (alignment
< ScreenWidth
)
254 alignment
= ScreenWidth
- alignment
;
255 for (size_t i
= 0; i
< alignment
; ++i
)
260 if (Line
.length() > ScreenWidth
)
261 Line
.erase(ScreenWidth
);
262 sigprocmask(SIG_SETMASK
,&OldSigs
,0);
264 // Draw the current status
265 if (_config
->FindB("Apt::Color", false) == true)
266 out
<< _config
->Find("APT::Color::Yellow");
267 if (LastLineLength
> Line
.length())
271 out
<< Line
<< std::flush
;
272 if (_config
->FindB("Apt::Color", false) == true)
273 out
<< _config
->Find("APT::Color::Neutral") << std::flush
;
275 LastLineLength
= Line
.length();
281 // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/
282 // ---------------------------------------------------------------------
283 /* Prompt for a media swap */
284 bool AcqTextStatus::MediaChange(std::string Media
, std::string Drive
)
286 // If we do not output on a terminal and one of the options to avoid user
287 // interaction is given, we assume that no user is present who could react
288 // on your media change request
289 if (isatty(STDOUT_FILENO
) != 1 && Quiet
>= 2 &&
290 (_config
->FindB("APT::Get::Assume-Yes",false) == true ||
291 _config
->FindB("APT::Get::Force-Yes",false) == true ||
292 _config
->FindB("APT::Get::Trivial-Only",false) == true))
297 ioprintf(out
,_("Media change: please insert the disc labeled\n"
299 "in the drive '%s' and press enter\n"),
300 Media
.c_str(),Drive
.c_str());
304 while (C
!= '\n' && C
!= '\r')
306 int len
= read(STDIN_FILENO
,&C
,1);
307 if(C
== 'c' || len
<= 0)
316 void AcqTextStatus::clearLastLine() { /*{{{*/
317 if (Quiet
> 0 || LastLineLength
== 0)
320 // do not try to clear more than the (now smaller) screen
321 if (LastLineLength
> ScreenWidth
)
322 LastLineLength
= ScreenWidth
;
325 for (size_t i
= 0; i
< LastLineLength
; ++i
)
327 out
<< '\r' << std::flush
;