You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

290 lines
8.0 KiB

  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: acqprogress.cc,v 1.24 2003/04/27 01:56:48 doogie Exp $
  4. /* ######################################################################
  5. Acquire Progress - Command line progress meter
  6. ##################################################################### */
  7. /*}}}*/
  8. // Include files /*{{{*/
  9. #include "acqprogress.h"
  10. #include <apt-pkg/acquire-item.h>
  11. #include <apt-pkg/acquire-worker.h>
  12. #include <apt-pkg/strutl.h>
  13. #include <apt-pkg/error.h>
  14. #include <apti18n.h>
  15. #include <stdio.h>
  16. #include <signal.h>
  17. #include <iostream>
  18. /*}}}*/
  19. using namespace std;
  20. // AcqTextStatus::AcqTextStatus - Constructor /*{{{*/
  21. // ---------------------------------------------------------------------
  22. /* */
  23. AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
  24. ScreenWidth(ScreenWidth), Quiet(Quiet)
  25. {
  26. }
  27. /*}}}*/
  28. // AcqTextStatus::Start - Downloading has started /*{{{*/
  29. // ---------------------------------------------------------------------
  30. /* */
  31. void AcqTextStatus::Start()
  32. {
  33. pkgAcquireStatus::Start();
  34. BlankLine[0] = 0;
  35. ID = 1;
  36. };
  37. /*}}}*/
  38. // AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/
  39. // ---------------------------------------------------------------------
  40. /* */
  41. void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm)
  42. {
  43. if (Quiet > 1)
  44. return;
  45. if (Quiet <= 0)
  46. cout << '\r' << BlankLine << '\r';
  47. cout << _("Hit ") << Itm.Description;
  48. if (Itm.Owner->FileSize != 0)
  49. cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]";
  50. cout << endl;
  51. Update = true;
  52. };
  53. /*}}}*/
  54. // AcqTextStatus::Fetch - An item has started to download /*{{{*/
  55. // ---------------------------------------------------------------------
  56. /* This prints out the short description and the expected size */
  57. void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm)
  58. {
  59. Update = true;
  60. if (Itm.Owner->Complete == true)
  61. return;
  62. Itm.Owner->ID = ID++;
  63. if (Quiet > 1)
  64. return;
  65. if (Quiet <= 0)
  66. cout << '\r' << BlankLine << '\r';
  67. cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description;
  68. if (Itm.Owner->FileSize != 0)
  69. cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]";
  70. cout << endl;
  71. };
  72. /*}}}*/
  73. // AcqTextStatus::Done - Completed a download /*{{{*/
  74. // ---------------------------------------------------------------------
  75. /* We don't display anything... */
  76. void AcqTextStatus::Done(pkgAcquire::ItemDesc &Itm)
  77. {
  78. Update = true;
  79. };
  80. /*}}}*/
  81. // AcqTextStatus::Fail - Called when an item fails to download /*{{{*/
  82. // ---------------------------------------------------------------------
  83. /* We print out the error text */
  84. void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm)
  85. {
  86. if (Quiet > 1)
  87. return;
  88. // Ignore certain kinds of transient failures (bad code)
  89. if (Itm.Owner->Status == pkgAcquire::Item::StatIdle)
  90. return;
  91. if (Quiet <= 0)
  92. cout << '\r' << BlankLine << '\r';
  93. if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
  94. {
  95. cout << _("Ign ") << Itm.Description << endl;
  96. }
  97. else
  98. {
  99. cout << _("Err ") << Itm.Description << endl;
  100. cout << " " << Itm.Owner->ErrorText << endl;
  101. }
  102. Update = true;
  103. };
  104. /*}}}*/
  105. // AcqTextStatus::Stop - Finished downloading /*{{{*/
  106. // ---------------------------------------------------------------------
  107. /* This prints out the bytes downloaded and the overall average line
  108. speed */
  109. void AcqTextStatus::Stop()
  110. {
  111. pkgAcquireStatus::Stop();
  112. if (Quiet > 1)
  113. return;
  114. if (Quiet <= 0)
  115. cout << '\r' << BlankLine << '\r' << flush;
  116. if (FetchedBytes != 0 && _error->PendingError() == false)
  117. ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"),
  118. SizeToStr(FetchedBytes).c_str(),
  119. TimeToStr(ElapsedTime).c_str(),
  120. SizeToStr(CurrentCPS).c_str());
  121. }
  122. /*}}}*/
  123. // AcqTextStatus::Pulse - Regular event pulse /*{{{*/
  124. // ---------------------------------------------------------------------
  125. /* This draws the current progress. Each line has an overall percent
  126. meter and a per active item status meter along with an overall
  127. bandwidth and ETA indicator. */
  128. bool AcqTextStatus::Pulse(pkgAcquire *Owner)
  129. {
  130. pkgAcquireStatus::Pulse(Owner);
  131. if (Quiet > 0)
  132. return true;
  133. enum {Long = 0,Medium,Short} Mode = Medium;
  134. char Buffer[sizeof(BlankLine)];
  135. char *End = Buffer + sizeof(Buffer);
  136. char *S = Buffer;
  137. if (ScreenWidth >= sizeof(Buffer))
  138. ScreenWidth = sizeof(Buffer)-1;
  139. // Put in the percent done
  140. sprintf(S,"%ld%%",long(double((CurrentBytes + CurrentItems)*100.0)/double(TotalBytes+TotalItems)));
  141. bool Shown = false;
  142. for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
  143. I = Owner->WorkerStep(I))
  144. {
  145. S += strlen(S);
  146. // There is no item running
  147. if (I->CurrentItem == 0)
  148. {
  149. if (I->Status.empty() == false)
  150. {
  151. snprintf(S,End-S," [%s]",I->Status.c_str());
  152. Shown = true;
  153. }
  154. continue;
  155. }
  156. Shown = true;
  157. // Add in the short description
  158. if (I->CurrentItem->Owner->ID != 0)
  159. snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID,
  160. I->CurrentItem->ShortDesc.c_str());
  161. else
  162. snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str());
  163. S += strlen(S);
  164. // Show the short mode string
  165. if (I->CurrentItem->Owner->Mode != 0)
  166. {
  167. snprintf(S,End-S," %s",I->CurrentItem->Owner->Mode);
  168. S += strlen(S);
  169. }
  170. // Add the current progress
  171. if (Mode == Long)
  172. snprintf(S,End-S," %lu",I->CurrentSize);
  173. else
  174. {
  175. if (Mode == Medium || I->TotalSize == 0)
  176. snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str());
  177. }
  178. S += strlen(S);
  179. // Add the total size and percent
  180. if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false)
  181. {
  182. if (Mode == Short)
  183. snprintf(S,End-S," %lu%%",
  184. long(double(I->CurrentSize*100.0)/double(I->TotalSize)));
  185. else
  186. snprintf(S,End-S,"/%sB %lu%%",SizeToStr(I->TotalSize).c_str(),
  187. long(double(I->CurrentSize*100.0)/double(I->TotalSize)));
  188. }
  189. S += strlen(S);
  190. snprintf(S,End-S,"]");
  191. }
  192. // Show something..
  193. if (Shown == false)
  194. snprintf(S,End-S,_(" [Working]"));
  195. /* Put in the ETA and cps meter, block off signals to prevent strangeness
  196. during resizing */
  197. sigset_t Sigs,OldSigs;
  198. sigemptyset(&Sigs);
  199. sigaddset(&Sigs,SIGWINCH);
  200. sigprocmask(SIG_BLOCK,&Sigs,&OldSigs);
  201. if (CurrentCPS != 0)
  202. {
  203. char Tmp[300];
  204. unsigned long ETA = (unsigned long)((TotalBytes - CurrentBytes)/CurrentCPS);
  205. sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str());
  206. unsigned int Len = strlen(Buffer);
  207. unsigned int LenT = strlen(Tmp);
  208. if (Len + LenT < ScreenWidth)
  209. {
  210. memset(Buffer + Len,' ',ScreenWidth - Len);
  211. strcpy(Buffer + ScreenWidth - LenT,Tmp);
  212. }
  213. }
  214. Buffer[ScreenWidth] = 0;
  215. BlankLine[ScreenWidth] = 0;
  216. sigprocmask(SIG_SETMASK,&OldSigs,0);
  217. // Draw the current status
  218. if (strlen(Buffer) == strlen(BlankLine))
  219. cout << '\r' << Buffer << flush;
  220. else
  221. cout << '\r' << BlankLine << '\r' << Buffer << flush;
  222. memset(BlankLine,' ',strlen(Buffer));
  223. BlankLine[strlen(Buffer)] = 0;
  224. Update = false;
  225. return true;
  226. }
  227. /*}}}*/
  228. // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/
  229. // ---------------------------------------------------------------------
  230. /* Prompt for a media swap */
  231. bool AcqTextStatus::MediaChange(string Media,string Drive)
  232. {
  233. if (Quiet <= 0)
  234. cout << '\r' << BlankLine << '\r';
  235. ioprintf(cout,_("Media change: please insert the disc labeled\n"
  236. " '%s'\n"
  237. "in the drive '%s' and press enter\n"),
  238. Media.c_str(),Drive.c_str());
  239. char C = 0;
  240. bool bStatus = true;
  241. while (C != '\n' && C != '\r')
  242. {
  243. int len = read(STDIN_FILENO,&C,1);
  244. if(C == 'c' || len <= 0)
  245. bStatus = false;
  246. }
  247. if(bStatus)
  248. Update = true;
  249. return bStatus;
  250. }
  251. /*}}}*/