]>
git.saurik.com Git - apt.git/blob - apt-private/acqprogress.cc
dcc538a3969b4eb168b14244827c178b668df4fc
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
);
179 enum {Long
= 0,Medium
,Short
} Mode
= Medium
;
184 for (pkgAcquire::Worker
*I
= Owner
->WorkersBegin(); I
!= 0;
185 I
= Owner
->WorkerStep(I
))
187 // There is no item running
188 if (I
->CurrentItem
== 0)
190 if (I
->Status
.empty() == false)
191 S
<< " [" << I
->Status
<< "]";
196 // Add in the short description
198 if (I
->CurrentItem
->Owner
->ID
!= 0)
199 S
<< I
->CurrentItem
->Owner
->ID
<< " ";
200 S
<< I
->CurrentItem
->ShortDesc
;
202 // Show the short mode string
203 if (I
->CurrentItem
->Owner
->ActiveSubprocess
.empty() == false)
204 S
<< " " << I
->CurrentItem
->Owner
->ActiveSubprocess
;
206 // Add the current progress
208 S
<< " " << I
->CurrentSize
;
211 if (Mode
== Medium
|| I
->TotalSize
== 0)
212 S
<< " " << SizeToStr(I
->CurrentSize
) << "B";
215 // Add the total size and percent
216 if (I
->TotalSize
> 0 && I
->CurrentItem
->Owner
->Complete
== false)
219 ioprintf(S
, " %.0f%%", (I
->CurrentSize
*100.0)/I
->TotalSize
);
221 ioprintf(S
, "/%sB %.0f%%", SizeToStr(I
->TotalSize
).c_str(),
222 (I
->CurrentSize
*100.0)/I
->TotalSize
);
227 // Show at least something
230 if (Line
.empty() == true)
231 Line
= _(" [Working]");
233 // Put in the percent done
236 ioprintf(S
, "%.0f%%", Percent
);
242 /* Put in the ETA and cps meter, block off signals to prevent strangeness
244 sigset_t Sigs
,OldSigs
;
246 sigaddset(&Sigs
,SIGWINCH
);
247 sigprocmask(SIG_BLOCK
,&Sigs
,&OldSigs
);
251 unsigned long long ETA
= (TotalBytes
- CurrentBytes
)/CurrentCPS
;
252 std::string Tmp
= " " + SizeToStr(CurrentCPS
) + "B/s " + TimeToStr(ETA
);
253 size_t alignment
= Line
.length() + Tmp
.length();
254 if (alignment
< ScreenWidth
)
256 alignment
= ScreenWidth
- alignment
;
257 for (size_t i
= 0; i
< alignment
; ++i
)
262 if (Line
.length() > ScreenWidth
)
263 Line
.erase(ScreenWidth
);
264 sigprocmask(SIG_SETMASK
,&OldSigs
,0);
266 // Draw the current status
267 if (_config
->FindB("Apt::Color", false) == true)
268 out
<< _config
->Find("APT::Color::Yellow");
269 if (LastLineLength
> Line
.length())
273 out
<< Line
<< std::flush
;
274 if (_config
->FindB("Apt::Color", false) == true)
275 out
<< _config
->Find("APT::Color::Neutral") << std::flush
;
277 LastLineLength
= Line
.length();
283 // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/
284 // ---------------------------------------------------------------------
285 /* Prompt for a media swap */
286 bool AcqTextStatus::MediaChange(std::string Media
, std::string Drive
)
288 // If we do not output on a terminal and one of the options to avoid user
289 // interaction is given, we assume that no user is present who could react
290 // on your media change request
291 if (isatty(STDOUT_FILENO
) != 1 && Quiet
>= 2 &&
292 (_config
->FindB("APT::Get::Assume-Yes",false) == true ||
293 _config
->FindB("APT::Get::Force-Yes",false) == true ||
294 _config
->FindB("APT::Get::Trivial-Only",false) == true))
299 ioprintf(out
,_("Media change: please insert the disc labeled\n"
301 "in the drive '%s' and press [Enter]\n"),
302 Media
.c_str(),Drive
.c_str());
306 while (C
!= '\n' && C
!= '\r')
308 int len
= read(STDIN_FILENO
,&C
,1);
309 if(C
== 'c' || len
<= 0)
318 void AcqTextStatus::clearLastLine() { /*{{{*/
319 if (Quiet
> 0 || LastLineLength
== 0)
322 // do not try to clear more than the (now smaller) screen
323 if (LastLineLength
> ScreenWidth
)
324 LastLineLength
= ScreenWidth
;
327 for (size_t i
= 0; i
< LastLineLength
; ++i
)
329 out
<< '\r' << std::flush
;