]>
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 // AcqTextStatus::IMSHit - Called when an item got a HIT response       /*{{{*/ 
  53 // --------------------------------------------------------------------- 
  55 void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc 
&Itm
) 
  62    out 
<< _("Hit ") << Itm
.Description
; 
  67 // AcqTextStatus::Fetch - An item has started to download               /*{{{*/ 
  68 // --------------------------------------------------------------------- 
  69 /* This prints out the short description and the expected size */ 
  70 void AcqTextStatus::Fetch(pkgAcquire::ItemDesc 
&Itm
) 
  73    if (Itm
.Owner
->Complete 
== true) 
  83    out 
<< _("Get:") << Itm
.Owner
->ID 
<< ' ' << Itm
.Description
; 
  84    if (Itm
.Owner
->FileSize 
!= 0) 
  85       out 
<< " [" << SizeToStr(Itm
.Owner
->FileSize
) << "B]"; 
  89 // AcqTextStatus::Done - Completed a download                           /*{{{*/ 
  90 // --------------------------------------------------------------------- 
  91 /* We don't display anything... */ 
  92 void AcqTextStatus::Done(pkgAcquire::ItemDesc 
&/*Itm*/) 
  97 // AcqTextStatus::Fail - Called when an item fails to download          /*{{{*/ 
  98 // --------------------------------------------------------------------- 
  99 /* We print out the error text  */ 
 100 void AcqTextStatus::Fail(pkgAcquire::ItemDesc 
&Itm
) 
 105    // Ignore certain kinds of transient failures (bad code) 
 106    if (Itm
.Owner
->Status 
== pkgAcquire::Item::StatIdle
) 
 111    if (Itm
.Owner
->Status 
== pkgAcquire::Item::StatDone
) 
 113       out 
<< _("Ign ") << Itm
.Description 
<< std::endl
; 
 114       if (Itm
.Owner
->ErrorText
.empty() == false && 
 115             _config
->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true) 
 116          out 
<< "  " << Itm
.Owner
->ErrorText 
<< std::endl
; 
 120       out 
<< _("Err ") << Itm
.Description 
<< std::endl
; 
 121       out 
<< "  " << Itm
.Owner
->ErrorText 
<< std::endl
; 
 127 // AcqTextStatus::Stop - Finished downloading                           /*{{{*/ 
 128 // --------------------------------------------------------------------- 
 129 /* This prints out the bytes downloaded and the overall average line 
 131 void AcqTextStatus::Stop() 
 133    pkgAcquireStatus::Stop(); 
 139    if (_config
->FindB("quiet::NoStatistic", false) == true) 
 142    if (FetchedBytes 
!= 0 && _error
->PendingError() == false) 
 143       ioprintf(out
,_("Fetched %sB in %s (%sB/s)\n"), 
 144                SizeToStr(FetchedBytes
).c_str(), 
 145                TimeToStr(ElapsedTime
).c_str(), 
 146                SizeToStr(CurrentCPS
).c_str()); 
 149 // AcqTextStatus::Pulse - Regular event pulse                           /*{{{*/ 
 150 // --------------------------------------------------------------------- 
 151 /* This draws the current progress. Each line has an overall percent 
 152    meter and a per active item status meter along with an overall 
 153    bandwidth and ETA indicator. */ 
 154 bool AcqTextStatus::Pulse(pkgAcquire 
*Owner
) 
 156    pkgAcquireStatus::Pulse(Owner
); 
 161    enum {Long 
= 0,Medium
,Short
} Mode 
= Medium
; 
 166       for (pkgAcquire::Worker 
*I 
= Owner
->WorkersBegin(); I 
!= 0; 
 167             I 
= Owner
->WorkerStep(I
)) 
 169          // There is no item running 
 170          if (I
->CurrentItem 
== 0) 
 172             if (I
->Status
.empty() == false) 
 173                S 
<< " [" << I
->Status 
<< "]"; 
 178          // Add in the short description 
 180          if (I
->CurrentItem
->Owner
->ID 
!= 0) 
 181             S 
<< I
->CurrentItem
->Owner
->ID 
<< " "; 
 182          S 
<< I
->CurrentItem
->ShortDesc
; 
 184          // Show the short mode string 
 185          if (I
->CurrentItem
->Owner
->ActiveSubprocess
.empty() == false) 
 186             S 
<< " " << I
->CurrentItem
->Owner
->ActiveSubprocess
; 
 188          // Add the current progress 
 190             S 
<< " " << I
->CurrentSize
; 
 193             if (Mode 
== Medium 
|| I
->TotalSize 
== 0) 
 194                S 
<< " " << SizeToStr(I
->CurrentSize
) << "B"; 
 197          // Add the total size and percent 
 198          if (I
->TotalSize 
> 0 && I
->CurrentItem
->Owner
->Complete 
== false) 
 201                ioprintf(S
, " %.0f%%", (I
->CurrentSize
*100.0)/I
->TotalSize
); 
 203                ioprintf(S
, "/%sB %.0f%%", SizeToStr(I
->TotalSize
).c_str(), 
 204                      (I
->CurrentSize
*100.0)/I
->TotalSize
); 
 209       // Show at least something 
 212       if (Line
.empty() == true) 
 213          Line 
= _(" [Working]"); 
 215    // Put in the percent done 
 218       ioprintf(S
, "%.0f%%", Percent
); 
 224    /* Put in the ETA and cps meter, block off signals to prevent strangeness 
 226    sigset_t Sigs
,OldSigs
; 
 228    sigaddset(&Sigs
,SIGWINCH
); 
 229    sigprocmask(SIG_BLOCK
,&Sigs
,&OldSigs
); 
 233       unsigned long long ETA 
= (TotalBytes 
- CurrentBytes
)/CurrentCPS
; 
 234       std::string Tmp 
= " " + SizeToStr(CurrentCPS
) + "B/s " + TimeToStr(ETA
); 
 235       size_t alignment 
= Line
.length() + Tmp
.length(); 
 236       if (alignment 
< ScreenWidth
) 
 238          alignment 
= ScreenWidth 
- alignment
; 
 239          for (size_t i 
= 0; i 
< alignment
; ++i
) 
 244    if (Line
.length() > ScreenWidth
) 
 245       Line
.erase(ScreenWidth
); 
 246    sigprocmask(SIG_SETMASK
,&OldSigs
,0); 
 248    // Draw the current status 
 249    if (_config
->FindB("Apt::Color", false) == true) 
 250       out 
<< _config
->Find("APT::Color::Yellow"); 
 251    if (LastLineLength 
> Line
.length()) 
 255    out 
<< Line 
<< std::flush
; 
 256    if (_config
->FindB("Apt::Color", false) == true) 
 257       out 
<< _config
->Find("APT::Color::Neutral") << std::flush
; 
 259    LastLineLength 
= Line
.length(); 
 265 // AcqTextStatus::MediaChange - Media need to be swapped                /*{{{*/ 
 266 // --------------------------------------------------------------------- 
 267 /* Prompt for a media swap */ 
 268 bool AcqTextStatus::MediaChange(std::string Media
, std::string Drive
) 
 270    // If we do not output on a terminal and one of the options to avoid user 
 271    // interaction is given, we assume that no user is present who could react 
 272    // on your media change request 
 273    if (isatty(STDOUT_FILENO
) != 1 && Quiet 
>= 2 && 
 274        (_config
->FindB("APT::Get::Assume-Yes",false) == true || 
 275         _config
->FindB("APT::Get::Force-Yes",false) == true || 
 276         _config
->FindB("APT::Get::Trivial-Only",false) == true)) 
 281    ioprintf(out
,_("Media change: please insert the disc labeled\n" 
 283                    "in the drive '%s' and press enter\n"), 
 284             Media
.c_str(),Drive
.c_str()); 
 288    while (C 
!= '\n' && C 
!= '\r') 
 290       int len 
= read(STDIN_FILENO
,&C
,1); 
 291       if(C 
== 'c' || len 
<= 0) 
 300 void AcqTextStatus::clearLastLine() {                                   /*{{{*/ 
 301    if (Quiet 
> 0 || LastLineLength 
== 0) 
 304    // do not try to clear more than the (now smaller) screen 
 305    if (LastLineLength 
> ScreenWidth
) 
 306       LastLineLength 
= ScreenWidth
; 
 309    for (size_t i 
= 0; i 
< LastLineLength
; ++i
) 
 311    out 
<< '\r' << std::flush
;