Browse Source

first iteration of install progress refactor

tags/debian/0.9.13.exp1
Michael Vogt 8 years ago
parent
commit
31f97d7b86
6 changed files with 194 additions and 93 deletions
  1. +20
    -91
      apt-pkg/deb/dpkgpm.cc
  2. +1
    -0
      apt-pkg/deb/dpkgpm.h
  3. +111
    -0
      apt-pkg/iprogress.cc
  4. +59
    -0
      apt-pkg/iprogress.h
  5. +2
    -2
      apt-pkg/makefile
  6. +1
    -0
      apt-pkg/packagemanager.h

+ 20
- 91
apt-pkg/deb/dpkgpm.cc View File

@@ -19,6 +19,7 @@
#include <apt-pkg/fileutl.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/packagemanager.h>
#include <apt-pkg/iprogress.h>

#include <unistd.h>
#include <stdlib.h>
@@ -54,16 +55,21 @@ class pkgDPkgPMPrivate
public:
pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
term_out(NULL), history_out(NULL),
last_reported_progress(0.0), nr_terminal_rows(0),
fancy_progress_output(false)
last_reported_progress(0.0)
{
dpkgbuf[0] = '\0';
if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
{
fancy_progress_output = true;
_config->Set("DpkgPM::Progress", true);
}
if(_config->FindB("DpkgPM::Progress-Fancy", false) == true)
progress = new APT::Progress::PackageManagerFancy();
else if (_config->FindB("DpkgPM::Progress", false) == true)
progress = new APT::Progress::PackageManagerText();
else
progress = new APT::Progress::PackageManager();
}
~pkgDPkgPMPrivate()
{
delete progress;
}

bool stdin_is_dev_null;
// the buffer we use for the dpkg status-fd reading
char dpkgbuf[1024];
@@ -73,8 +79,7 @@ public:
string dpkg_error;

float last_reported_progress;
int nr_terminal_rows;
bool fancy_progress_output;
APT::Progress::PackageManager *progress;
};

namespace
@@ -644,8 +649,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
<< ":" << (PackagesDone/float(PackagesTotal)*100.0)
<< ":" << s
<< endl;
if(_config->FindB("DPkgPM::Progress", false) == true)
SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0);
d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal);

if(OutStatusFd > 0)
FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size());
@@ -889,52 +893,6 @@ bool pkgDPkgPM::CloseLog()
return true;
}
/*}}}*/
// DPkgPM::SendTerminalProgress /*{{{*/
// ---------------------------------------------------------------------
/* Send progress info to the terminal
*/
void pkgDPkgPM::SendTerminalProgress(float percentage)
{
int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);

if(percentage < (d->last_reported_progress + reporting_steps))
return;

std::string progress_str;
strprintf(progress_str, "Progress: [%3i%%]", (int)percentage);
if (d->fancy_progress_output)
{
int row = d->nr_terminal_rows;

static string save_cursor = "\033[s";
static string restore_cursor = "\033[u";

static string set_bg_color = "\033[42m"; // green
static string set_fg_color = "\033[30m"; // black

static string restore_bg = "\033[49m";
static string restore_fg = "\033[39m";

std::cout << save_cursor
// move cursor position to last row
<< "\033[" << row << ";0f"
<< set_bg_color
<< set_fg_color
<< progress_str
<< restore_cursor
<< restore_bg
<< restore_fg;
}
else
{
std::cout << progress_str << "\r\n";
}
std::flush(std::cout);
d->last_reported_progress = percentage;
}
/*}}}*/
/*{{{*/
// This implements a racy version of pselect for those architectures
// that don't have a working implementation.
// FIXME: Probably can be removed on Lenny+1
@@ -956,27 +914,6 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
}
/*}}}*/

void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows)
{
if(!d->fancy_progress_output)
return;

// scroll down a bit to avoid visual glitch when the screen
// area shrinks by one row
std::cout << "\n";
// save cursor
std::cout << "\033[s";
// set scroll region (this will place the cursor in the top left)
std::cout << "\033[1;" << nr_rows - 1 << "r";
// restore cursor but ensure its inside the scrolling area
std::cout << "\033[u";
static const char *move_cursor_up = "\033[1A";
std::cout << move_cursor_up;
std::flush(std::cout);
}

// DPkgPM::Go - Run the sequence /*{{{*/
// ---------------------------------------------------------------------
@@ -1334,8 +1271,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
_error->PushToStack();
if (tcgetattr(STDOUT_FILENO, &tt) == 0)
{
ioctl(1, TIOCGWINSZ, (char *)&win);
d->nr_terminal_rows = win.ws_row;
ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win);
if (openpty(&master, &slave, NULL, &tt, &win) < 0)
{
_error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
@@ -1415,7 +1351,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
_exit(100);
}
SetupTerminalScrollArea(d->nr_terminal_rows);

/* No Job Control Stop Env is a magic dpkg var that prevents it
from using sigstop */
@@ -1424,6 +1359,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
cerr << "Could not exec dpkg!" << endl;
_exit(100);
}
d->progress->Started();

// apply ionice
if (_config->FindB("DPkg::UseIoNice", false) == true)
@@ -1510,14 +1446,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
signal(SIGHUP,old_SIGHUP);

// reset scroll area
SetupTerminalScrollArea(d->nr_terminal_rows + 1);
if(d->fancy_progress_output)
{
// override the progress line (sledgehammer)
static const char* clear_screen_below_cursor = "\033[J";
std::cout << clear_screen_below_cursor;
}
// tell the progress
d->progress->Finished();

if(master >= 0)
{
@@ -1556,8 +1486,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
CloseLog();

// dpkg is done at this point
if(_config->FindB("DPkgPM::Progress", false) == true)
SendTerminalProgress(100);
d->progress->StatusChanged("", PackagesDone, PackagesTotal);

if (pkgPackageManager::SigINTStop)
_error->Warning(_("Operation was interrupted before it could finish"));


+ 1
- 0
apt-pkg/deb/dpkgpm.h View File

@@ -23,6 +23,7 @@ using std::map;

class pkgDPkgPMPrivate;


class pkgDPkgPM : public pkgPackageManager
{
private:


+ 111
- 0
apt-pkg/iprogress.cc View File

@@ -0,0 +1,111 @@
#include <apt-pkg/iprogress.h>
#include <apt-pkg/strutl.h>

#include <termios.h>
#include <sys/ioctl.h>

namespace APT {
namespace Progress {

static void SetupTerminalScrollArea(int nr_rows)
{
// scroll down a bit to avoid visual glitch when the screen
// area shrinks by one row
std::cout << "\n";
// save cursor
std::cout << "\033[s";
// set scroll region (this will place the cursor in the top left)
std::cout << "\033[1;" << nr_rows - 1 << "r";
// restore cursor but ensure its inside the scrolling area
std::cout << "\033[u";
static const char *move_cursor_up = "\033[1A";
std::cout << move_cursor_up;
std::flush(std::cout);
}

PackageManagerFancy::PackageManagerFancy()
: nr_terminal_rows(-1)
{
struct winsize win;
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0)
{
nr_terminal_rows = win.ws_row;
}
}

void PackageManagerFancy::Started()
{
SetupTerminalScrollArea(nr_terminal_rows);
}

void PackageManagerFancy::Finished()
{
SetupTerminalScrollArea(nr_terminal_rows + 1);

// override the progress line (sledgehammer)
static const char* clear_screen_below_cursor = "\033[J";
std::cout << clear_screen_below_cursor;
}

void PackageManagerFancy::StatusChanged(std::string PackageName,
unsigned int StepsDone,
unsigned int TotalSteps)
{
int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);
float percentage = StepsDone/(float)TotalSteps * 100.0;

if(percentage < (last_reported_progress + reporting_steps))
return;

std::string progress_str;
strprintf(progress_str, "Progress: [%3i%%]", (int)percentage);

int row = nr_terminal_rows;

static string save_cursor = "\033[s";
static string restore_cursor = "\033[u";
static string set_bg_color = "\033[42m"; // green
static string set_fg_color = "\033[30m"; // black
static string restore_bg = "\033[49m";
static string restore_fg = "\033[39m";
std::cout << save_cursor
// move cursor position to last row
<< "\033[" << row << ";0f"
<< set_bg_color
<< set_fg_color
<< progress_str
<< restore_cursor
<< restore_bg
<< restore_fg;
std::flush(std::cout);
last_reported_progress = percentage;
}

void PackageManagerText::StatusChanged(std::string PackageName,
unsigned int StepsDone,
unsigned int TotalSteps)
{
int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);
float percentage = StepsDone/(float)TotalSteps * 100.0;

if(percentage < (last_reported_progress + reporting_steps))
return;

std::string progress_str;
strprintf(progress_str, "Progress: [%3i%%]", (int)percentage);

std::cout << progress_str << "\r\n";
std::flush(std::cout);
last_reported_progress = percentage;
}


}; // namespace progress
}; // namespace apt

+ 59
- 0
apt-pkg/iprogress.h View File

@@ -0,0 +1,59 @@
#ifndef PKGLIB_IPROGRESS_H
#define PKGLIB_IPROGRSS_H


#include <apt-pkg/packagemanager.h>

namespace APT {
namespace Progress {


class PackageManager
{
private:
/** \brief dpointer placeholder */
void *d;

public:
virtual ~PackageManager() {};

virtual void Started() {};
virtual void Finished() {};
virtual void StatusChanged(std::string PackageName,
unsigned int StepsDone,
unsigned int TotalSteps) {};
};

class PackageManagerFancy : public PackageManager
{
protected:
int last_reported_progress;
int nr_terminal_rows;
public:
PackageManagerFancy();
virtual void Started();
virtual void Finished();
virtual void StatusChanged(std::string PackageName,
unsigned int StepsDone,
unsigned int TotalSteps);
};

class PackageManagerText : public PackageManager
{
protected:
int last_reported_progress;

public:
PackageManagerText() : last_reported_progress(0) {};
virtual void StatusChanged(std::string PackageName,
unsigned int StepsDone,
unsigned int TotalSteps);

};


}; // namespace Progress
}; // namespace APT

#endif

+ 2
- 2
apt-pkg/makefile View File

@@ -43,7 +43,7 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc
aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc iprogress.cc
HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
orderlist.h sourcelist.h packagemanager.h tagfile.h \
init.h pkgcache.h version.h progress.h pkgrecords.h \
@@ -51,7 +51,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
cachefilter.h cacheset.h edsp.h
cachefilter.h cacheset.h edsp.h iprogress.h

# Source code for the debian specific components
# In theory the deb headers do not need to be exported..


+ 1
- 0
apt-pkg/packagemanager.h View File

@@ -39,6 +39,7 @@ class pkgDepCache;
class pkgSourceList;
class pkgOrderList;
class pkgRecords;

class pkgPackageManager : protected pkgCache::Namespace
{
public:


Loading…
Cancel
Save