Package: apt-move Version: 4.2.23 Followup-For: Bug #74784 Hi
I wrote a patch for fetch.cc to get a download progress indicator. It can be switch of with the "-q" option from apt-move. acqprogress.cc and acqprogress.h come from the apt source. Robert *** apt-move-4.2.23-download-progress.patch diff -Naur apt-move-4.2.23/acqprogress.cc apt-move-4.2.23-download-progress/acqprogress.cc --- apt-move-4.2.23/acqprogress.cc 1970-01-01 01:00:00.000000000 +0100 +++ apt-move-4.2.23-download-progress/acqprogress.cc 2005-05-31 00:21:02.000000000 +0200 @@ -0,0 +1,283 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: acqprogress.cc,v 1.24 2003/04/27 01:56:48 doogie Exp $ +/* ###################################################################### + + Acquire Progress - Command line progress meter + + ##################################################################### */ + /*}}}*/ +// Include files /*{{{*/ +#include "acqprogress.h" +#include <apt-pkg/acquire-item.h> +#include <apt-pkg/acquire-worker.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/error.h> + +//#include <apti18n.h> + +#include <stdio.h> +#include <signal.h> +#include <iostream> + /*}}}*/ + +using namespace std; + +// AcqTextStatus::AcqTextStatus - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) : + ScreenWidth(ScreenWidth), Quiet(Quiet) +{ +} + /*}}}*/ +// AcqTextStatus::Start - Downloading has started /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void AcqTextStatus::Start() +{ + pkgAcquireStatus::Start(); + BlankLine[0] = 0; + ID = 1; +}; + /*}}}*/ +// AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm) +{ + if (Quiet > 1) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + + cout << "Hit " << Itm.Description; + if (Itm.Owner->FileSize != 0) + cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; + cout << endl; + Update = true; +}; + /*}}}*/ +// AcqTextStatus::Fetch - An item has started to download /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out the short description and the expected size */ +void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm) +{ + Update = true; + if (Itm.Owner->Complete == true) + return; + + Itm.Owner->ID = ID++; + + if (Quiet > 1) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + + cout << "Get:" << Itm.Owner->ID << ' ' << Itm.Description; + if (Itm.Owner->FileSize != 0) + cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; + cout << endl; +}; + /*}}}*/ +// AcqTextStatus::Done - Completed a download /*{{{*/ +// --------------------------------------------------------------------- +/* We don't display anything... */ +void AcqTextStatus::Done(pkgAcquire::ItemDesc &Itm) +{ + Update = true; +}; + /*}}}*/ +// AcqTextStatus::Fail - Called when an item fails to download /*{{{*/ +// --------------------------------------------------------------------- +/* We print out the error text */ +void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm) +{ + if (Quiet > 1) + return; + + // Ignore certain kinds of transient failures (bad code) + if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + + if (Itm.Owner->Status == pkgAcquire::Item::StatDone) + { + cout << "Ign " << Itm.Description << endl; + } + else + { + cout << "Err " << Itm.Description << endl; + cout << " " << Itm.Owner->ErrorText << endl; + } + + Update = true; +}; + /*}}}*/ +// AcqTextStatus::Stop - Finished downloading /*{{{*/ +// --------------------------------------------------------------------- +/* This prints out the bytes downloaded and the overall average line + speed */ +void AcqTextStatus::Stop() +{ + pkgAcquireStatus::Stop(); + if (Quiet > 1) + return; + + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r' << flush; + + if (FetchedBytes != 0 && _error->PendingError() == false) + ioprintf(cout,"Fetched %sB in %s (%sB/s)\n", + SizeToStr(FetchedBytes).c_str(), + TimeToStr(ElapsedTime).c_str(), + SizeToStr(CurrentCPS).c_str()); +} + /*}}}*/ +// AcqTextStatus::Pulse - Regular event pulse /*{{{*/ +// --------------------------------------------------------------------- +/* This draws the current progress. Each line has an overall percent + meter and a per active item status meter along with an overall + bandwidth and ETA indicator. */ +bool AcqTextStatus::Pulse(pkgAcquire *Owner) +{ + if (Quiet > 0) + return true; + + pkgAcquireStatus::Pulse(Owner); + + enum {Long = 0,Medium,Short} Mode = Long; + + char Buffer[sizeof(BlankLine)]; + char *End = Buffer + sizeof(Buffer); + char *S = Buffer; + if (ScreenWidth >= sizeof(Buffer)) + ScreenWidth = sizeof(Buffer)-1; + + // Put in the percent done + sprintf(S,"%ld%%",long(double((CurrentBytes + CurrentItems)*100.0)/double(TotalBytes+TotalItems))); + + bool Shown = false; + for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0; + I = Owner->WorkerStep(I)) + { + S += strlen(S); + + // There is no item running + if (I->CurrentItem == 0) + { + if (I->Status.empty() == false) + { + snprintf(S,End-S," [%s]",I->Status.c_str()); + Shown = true; + } + + continue; + } + + Shown = true; + + // Add in the short description + if (I->CurrentItem->Owner->ID != 0) + snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID, + I->CurrentItem->ShortDesc.c_str()); + else + snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str()); + S += strlen(S); + + // Show the short mode string + if (I->CurrentItem->Owner->Mode != 0) + { + snprintf(S,End-S," %s",I->CurrentItem->Owner->Mode); + S += strlen(S); + } + + // Add the current progress + if (Mode == Long) + snprintf(S,End-S," %lu",I->CurrentSize); + else + { + if (Mode == Medium || I->TotalSize == 0) + snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str()); + } + S += strlen(S); + + // Add the total size and percent + if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false) + { + if (Mode == Short) + snprintf(S,End-S," %lu%%", + long(double(I->CurrentSize*100.0)/double(I->TotalSize))); + else + snprintf(S,End-S,"/%sB %lu%%",SizeToStr(I->TotalSize).c_str(), + long(double(I->CurrentSize*100.0)/double(I->TotalSize))); + } + S += strlen(S); + snprintf(S,End-S,"]"); + } + + // Show something.. + if (Shown == false) + snprintf(S,End-S," [Working]"); + + /* Put in the ETA and cps meter, block off signals to prevent strangeness + during resizing */ + sigset_t Sigs,OldSigs; + sigemptyset(&Sigs); + sigaddset(&Sigs,SIGWINCH); + sigprocmask(SIG_BLOCK,&Sigs,&OldSigs); + + if (CurrentCPS != 0) + { + char Tmp[300]; + unsigned long ETA = (unsigned long)((TotalBytes - CurrentBytes)/CurrentCPS); + sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str()); + unsigned int Len = strlen(Buffer); + unsigned int LenT = strlen(Tmp); + if (Len + LenT < ScreenWidth) + { + memset(Buffer + Len,' ',ScreenWidth - Len); + strcpy(Buffer + ScreenWidth - LenT,Tmp); + } + } + Buffer[ScreenWidth] = 0; + BlankLine[ScreenWidth] = 0; + sigprocmask(SIG_SETMASK,&OldSigs,0); + + // Draw the current status + if (strlen(Buffer) == strlen(BlankLine)) + cout << '\r' << Buffer << flush; + else + cout << '\r' << BlankLine << '\r' << Buffer << flush; + memset(BlankLine,' ',strlen(Buffer)); + BlankLine[strlen(Buffer)] = 0; + + Update = false; + + return true; +} + /*}}}*/ +// AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/ +// --------------------------------------------------------------------- +/* Prompt for a media swap */ +bool AcqTextStatus::MediaChange(string Media,string Drive) +{ + if (Quiet <= 0) + cout << '\r' << BlankLine << '\r'; + ioprintf(cout,"Media Change: Please insert the disc labeled\n" + " '%s'\n" + "in the drive '%s' and press enter\n", + Media.c_str(),Drive.c_str()); + + char C = 0; + while (C != '\n' && C != '\r') + read(STDIN_FILENO,&C,1); + + Update = true; + return true; +} + /*}}}*/ diff -Naur apt-move-4.2.23/acqprogress.h apt-move-4.2.23-download-progress/acqprogress.h --- apt-move-4.2.23/acqprogress.h 1970-01-01 01:00:00.000000000 +0100 +++ apt-move-4.2.23-download-progress/acqprogress.h 2005-05-31 00:05:38.000000000 +0200 @@ -0,0 +1,37 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: acqprogress.h,v 1.5 2003/02/02 22:24:11 jgg Exp $ +/* ###################################################################### + + Acquire Progress - Command line progress meter + + ##################################################################### */ + /*}}}*/ +#ifndef ACQPROGRESS_H +#define ACQPROGRESS_H + +#include <apt-pkg/acquire.h> + +class AcqTextStatus : public pkgAcquireStatus +{ + unsigned int &ScreenWidth; + char BlankLine[1024]; + unsigned long ID; + unsigned long Quiet; + + public: + + virtual bool MediaChange(string Media,string Drive); + virtual void IMSHit(pkgAcquire::ItemDesc &Itm); + virtual void Fetch(pkgAcquire::ItemDesc &Itm); + virtual void Done(pkgAcquire::ItemDesc &Itm); + virtual void Fail(pkgAcquire::ItemDesc &Itm); + virtual void Start(); + virtual void Stop(); + + bool Pulse(pkgAcquire *Owner); + + AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet); +}; + +#endif diff -Naur apt-move-4.2.23/apt-move apt-move-4.2.23-download-progress/apt-move --- apt-move-4.2.23/apt-move 2004-11-22 00:04:26.000000000 +0100 +++ apt-move-4.2.23-download-progress/apt-move 2005-06-02 00:03:55.000000000 +0200 @@ -1433,7 +1433,11 @@ xargs -r $FETCH -t return 0 fi - xargs -r $FETCH + if [ $QUIET ]; then + xargs -r $FETCH -q + else + xargs -r $FETCH + fi } domove } diff -Naur apt-move-4.2.23/fetch.cc apt-move-4.2.23-download-progress/fetch.cc --- apt-move-4.2.23/fetch.cc 2004-11-21 23:23:15.000000000 +0100 +++ apt-move-4.2.23-download-progress/fetch.cc 2005-06-02 00:08:39.000000000 +0200 @@ -10,6 +10,11 @@ #include <stdlib.h> #include <unistd.h> +#include <sys/ioctl.h> +#include <signal.h> +#include <apt-pkg/strutl.h> +#include "acqprogress.h" + using std::cerr; using std::cout; using std::endl; @@ -19,6 +24,20 @@ #define NotSource pkgCache::Flag::NotSource #define NotAutomatic pkgCache::Flag::NotAutomatic +unsigned int ScreenWidth=80; + +// SigWinch - window size change signal handler +void SigWinch(int) +{ + // riped from GNU ls +#ifdef TIOCGWINSZ + struct winsize ws; + + if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5) + ScreenWidth = ws.ws_col - 1; +#endif +} + VerIterator getHighestVersion(pkgCache &cache, pkgCache::PkgIterator pkg) { VerIterator last(cache, 0); @@ -59,7 +78,9 @@ "Unable to lock the download directory"); } - pkgAcquire fetcher; + // Create the download object + AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); + pkgAcquire fetcher(&Stat); pkgSourceList list; if (!list.ReadMainList()) @@ -89,6 +110,18 @@ return true; } + // Display statistics + double FetchBytes = fetcher.FetchNeeded(); + double DebBytes = fetcher.TotalNeeded(); + + // Number of bytes + if (DebBytes != FetchBytes) + ioprintf(cout,"Need to get %sB/%sB of archives.\n", + SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str()); + else + ioprintf(cout,"Need to get %sB of archives.\n", + SizeToStr(DebBytes).c_str()); + if (fetcher.Run() == pkgAcquire::Failed) return false; @@ -96,20 +129,24 @@ } static void usage(const char *name) { - cerr << "usage: " << name << " [-t] pkg..." << endl; + cerr << "usage: " << name << " [-t] [-q] pkg..." << endl; exit(1); } int main(int argc, char **argv) { int test = 0; + int quiet = 0; const char *progname = argv[0]; int c; - while ((c = getopt(argc, argv, "t")) != -1) { + while ((c = getopt(argc, argv, "tq")) != -1) { switch (c) { case 't': test = 1; break; + case 'q': + quiet = 1; + break; default: usage(progname); } @@ -125,6 +162,13 @@ if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1) _config->Set("quiet","1"); + if (quiet) + _config->Set("quiet","2"); + + // setup the signals + signal(SIGWINCH,SigWinch); + SigWinch(0); + downloadPackages(test, argc, argv); if (!_error->empty()) { diff -Naur apt-move-4.2.23/Makefile apt-move-4.2.23-download-progress/Makefile --- apt-move-4.2.23/Makefile 2004-11-21 23:23:15.000000000 +0100 +++ apt-move-4.2.23-download-progress/Makefile 2005-05-31 00:37:03.000000000 +0200 @@ -14,7 +14,7 @@ all: fetch -fetch: fetch.o +fetch: fetch.o acqprogress.o $(CXX) -o $@ $(LDFLAGS) $^ $(LOADLIBS) $(LDLIBS) clean: -- System Information: Debian Release: 3.1 APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing') Architecture: i386 (i686) Locale: LANG=de_CH, LC_CTYPE=de_CH (charmap=ISO-8859-1) (ignored: LC_ALL set to de_CH) Versions of packages apt-move depends on: ii apt [libapt-pkg-libc6.3-5-3 0.5.28.6 Advanced front-end for dpkg ii bc 1.06-17 The GNU bc arbitrary precision cal ii coreutils 5.2.1-2 The GNU core utilities ii dash 0.5.2-2 The Debian Almquist Shell ii libc6 2.3.2.ds1-21 GNU C Library: Shared libraries an ii libgcc1 1:3.4.3-12 GCC support library ii libstdc++5 1:3.3.5-12 The GNU Standard C++ Library v3 ii mawk 1.3.3-11 a pattern scanning and text proces -- no debconf information -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]