]>
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)
40 if (Quiet
< 2 && _config
->FindB("quiet::NoProgress", false) == true)
44 // AcqTextStatus::Start - Downloading has started /*{{{*/
45 // ---------------------------------------------------------------------
47 void AcqTextStatus::Start()
49 pkgAcquireStatus::Start();
54 void AcqTextStatus::AssignItemID(pkgAcquire::ItemDesc
&Itm
) /*{{{*/
56 /* In theory calling it from Fetch() would be enough, but to be
57 safe we call it from IMSHit and Fail as well.
58 Also, an Item can pass through multiple stages, so ensure
59 that it keeps the same number */
60 if (Itm
.Owner
->ID
== 0)
64 // AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/
65 // ---------------------------------------------------------------------
67 void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc
&Itm
)
75 // TRANSLATOR: Very short word to be displayed before unchanged files in 'apt-get update'
76 ioprintf(out
, _("Hit:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
81 // AcqTextStatus::Fetch - An item has started to download /*{{{*/
82 // ---------------------------------------------------------------------
83 /* This prints out the short description and the expected size */
84 void AcqTextStatus::Fetch(pkgAcquire::ItemDesc
&Itm
)
87 if (Itm
.Owner
->Complete
== true)
96 // TRANSLATOR: Very short word to be displayed for files processed in 'apt-get update'
97 // Potentially replaced later by "Hit:", "Ign:" or "Err:" if something (bad) happens
98 ioprintf(out
, _("Get:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
99 if (Itm
.Owner
->FileSize
!= 0)
100 out
<< " [" << SizeToStr(Itm
.Owner
->FileSize
) << "B]";
104 // AcqTextStatus::Done - Completed a download /*{{{*/
105 // ---------------------------------------------------------------------
106 /* We don't display anything... */
107 void AcqTextStatus::Done(pkgAcquire::ItemDesc
&Itm
)
113 // AcqTextStatus::Fail - Called when an item fails to download /*{{{*/
114 // ---------------------------------------------------------------------
115 /* We print out the error text */
116 void AcqTextStatus::Fail(pkgAcquire::ItemDesc
&Itm
)
124 if (Itm
.Owner
->Status
== pkgAcquire::Item::StatDone
|| Itm
.Owner
->Status
== pkgAcquire::Item::StatIdle
)
126 // TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
127 // which failed to download, but the error is ignored (compare "Err:")
128 ioprintf(out
, _("Ign:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
129 if (Itm
.Owner
->ErrorText
.empty() == false &&
130 _config
->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true)
131 out
<< std::endl
<< " " << Itm
.Owner
->ErrorText
;
136 // TRANSLATOR: Very short word to be displayed for files in 'apt-get update'
137 // which failed to download and the error is critical (compare "Ign:")
138 ioprintf(out
, _("Err:%lu %s"), Itm
.Owner
->ID
, Itm
.Description
.c_str());
139 out
<< std::endl
<< " " << Itm
.Owner
->ErrorText
<< std::endl
;
145 // AcqTextStatus::Stop - Finished downloading /*{{{*/
146 // ---------------------------------------------------------------------
147 /* This prints out the bytes downloaded and the overall average line
149 void AcqTextStatus::Stop()
151 pkgAcquireStatus::Stop();
157 if (_config
->FindB("quiet::NoStatistic", false) == true)
160 if (FetchedBytes
!= 0 && _error
->PendingError() == false)
161 ioprintf(out
,_("Fetched %sB in %s (%sB/s)\n"),
162 SizeToStr(FetchedBytes
).c_str(),
163 TimeToStr(ElapsedTime
).c_str(),
164 SizeToStr(CurrentCPS
).c_str());
167 // AcqTextStatus::Pulse - Regular event pulse /*{{{*/
168 // ---------------------------------------------------------------------
169 /* This draws the current progress. Each line has an overall percent
170 meter and a per active item status meter along with an overall
171 bandwidth and ETA indicator. */
172 bool AcqTextStatus::Pulse(pkgAcquire
*Owner
)
174 pkgAcquireStatus::Pulse(Owner
);
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 enum {Long
= 0,Medium
,Short
} Mode
= Medium
;
205 // Add the current progress
207 S
<< " " << I
->CurrentSize
;
210 if (Mode
== Medium
|| I
->TotalSize
== 0)
211 S
<< " " << SizeToStr(I
->CurrentSize
) << "B";
214 // Add the total size and percent
215 if (I
->TotalSize
> 0 && I
->CurrentItem
->Owner
->Complete
== false)
218 ioprintf(S
, " %.0f%%", (I
->CurrentSize
*100.0)/I
->TotalSize
);
220 ioprintf(S
, "/%sB %.0f%%", SizeToStr(I
->TotalSize
).c_str(),
221 (I
->CurrentSize
*100.0)/I
->TotalSize
);
226 // Show at least something
229 if (Line
.empty() == true)
230 Line
= _(" [Working]");
232 // Put in the percent done
235 ioprintf(S
, "%.0f%%", Percent
);
241 /* Put in the ETA and cps meter, block off signals to prevent strangeness
243 sigset_t Sigs
,OldSigs
;
245 sigaddset(&Sigs
,SIGWINCH
);
246 sigprocmask(SIG_BLOCK
,&Sigs
,&OldSigs
);
250 unsigned long long ETA
= (TotalBytes
- CurrentBytes
)/CurrentCPS
;
251 std::string Tmp
= " " + SizeToStr(CurrentCPS
) + "B/s " + TimeToStr(ETA
);
252 size_t alignment
= Line
.length() + Tmp
.length();
253 if (alignment
< ScreenWidth
)
255 alignment
= ScreenWidth
- alignment
;
256 for (size_t i
= 0; i
< alignment
; ++i
)
261 if (Line
.length() > ScreenWidth
)
262 Line
.erase(ScreenWidth
);
263 sigprocmask(SIG_SETMASK
,&OldSigs
,0);
265 // Draw the current status
266 if (_config
->FindB("Apt::Color", false) == true)
267 out
<< _config
->Find("APT::Color::Yellow");
268 if (LastLineLength
> Line
.length())
272 out
<< Line
<< std::flush
;
273 if (_config
->FindB("Apt::Color", false) == true)
274 out
<< _config
->Find("APT::Color::Neutral") << std::flush
;
276 LastLineLength
= Line
.length();
282 // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/
283 // ---------------------------------------------------------------------
284 /* Prompt for a media swap */
285 bool AcqTextStatus::MediaChange(std::string Media
, std::string Drive
)
287 // If we do not output on a terminal and one of the options to avoid user
288 // interaction is given, we assume that no user is present who could react
289 // on your media change request
290 if (isatty(STDOUT_FILENO
) != 1 && Quiet
>= 2 &&
291 (_config
->FindB("APT::Get::Assume-Yes",false) == true ||
292 _config
->FindB("APT::Get::Force-Yes",false) == true ||
293 _config
->FindB("APT::Get::Trivial-Only",false) == true))
298 ioprintf(out
,_("Media change: please insert the disc labeled\n"
300 "in the drive '%s' and press [Enter]\n"),
301 Media
.c_str(),Drive
.c_str());
305 while (C
!= '\n' && C
!= '\r')
307 int len
= read(STDIN_FILENO
,&C
,1);
308 if(C
== 'c' || len
<= 0)
317 void AcqTextStatus::clearLastLine() { /*{{{*/
318 if (Quiet
> 0 || LastLineLength
== 0)
321 // do not try to clear more than the (now smaller) screen
322 if (LastLineLength
> ScreenWidth
)
323 LastLineLength
= ScreenWidth
;
326 for (size_t i
= 0; i
< LastLineLength
; ++i
)
328 out
<< '\r' << std::flush
;