Browse Source

add -o DpkgPM::Progress-Fancy for better dpkg progress output on vt100+ terminals

debian/1.8.y
Michael Vogt 9 years ago
parent
commit
af6b41692b
  1. 88
      apt-pkg/deb/dpkgpm.cc
  2. 2
      apt-pkg/deb/dpkgpm.h

88
apt-pkg/deb/dpkgpm.cc

@ -54,9 +54,15 @@ class pkgDPkgPMPrivate
public:
pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
term_out(NULL), history_out(NULL),
last_reported_progress(0.0)
last_reported_progress(0.0), nr_terminal_rows(0),
fancy_progress_output(false)
{
dpkgbuf[0] = '\0';
if(_config->FindB("DpkgPM::Progress-Fancy", false))
{
fancy_progress_output = true;
_config->Set("DpkgPM::Progress", true);
}
}
bool stdin_is_dev_null;
// the buffer we use for the dpkg status-fd reading
@ -67,6 +73,8 @@ public:
string dpkg_error;
float last_reported_progress;
int nr_terminal_rows;
bool fancy_progress_output;
};
namespace
@ -892,10 +900,37 @@ void pkgDPkgPM::SendTerminalProgress(float percentage)
if(percentage < (d->last_reported_progress + reporting_steps))
return;
// FIXME: use colors too
std::cout << "\r\n"
<< "Progress: [" << std::setw(3) << int(percentage) << "%]"
<< "\r\n";
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;
}
/*}}}*/
@ -920,6 +955,29 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
return retval;
}
/*}}}*/
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\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 /*{{{*/
// ---------------------------------------------------------------------
/* This globs the operations and calls dpkg
@ -1276,7 +1334,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
_error->PushToStack();
if (tcgetattr(STDOUT_FILENO, &tt) == 0)
{
ioctl(0, TIOCGWINSZ, (char *)&win);
ioctl(1, TIOCGWINSZ, (char *)&win);
d->nr_terminal_rows = win.ws_row;
if (openpty(&master, &slave, NULL, &tt, &win) < 0)
{
_error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
@ -1318,11 +1377,12 @@ bool pkgDPkgPM::Go(int OutStatusFd)
<< endl;
FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size());
}
Child = ExecFork();
// This is the child
if (Child == 0)
{
if(slave >= 0 && master >= 0)
{
setsid();
@ -1339,7 +1399,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
_exit(100);
if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
{
int Flags,dummy;
@ -1355,6 +1415,7 @@ 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 */
@ -1449,6 +1510,15 @@ bool pkgDPkgPM::Go(int OutStatusFd)
signal(SIGHUP,old_SIGHUP);
// reset scroll area
SetupTerminalScrollArea(d->nr_terminal_rows);
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;
}
if(master >= 0)
{
tcsetattr(0, TCSAFLUSH, &tt);
@ -1488,7 +1558,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// dpkg is done at this point
if(_config->FindB("DPkgPM::Progress", false) == true)
SendTerminalProgress(100);
if (pkgPackageManager::SigINTStop)
_error->Warning(_("Operation was interrupted before it could finish"));

2
apt-pkg/deb/dpkgpm.h

@ -84,6 +84,8 @@ class pkgDPkgPM : public pkgPackageManager
bool SendPkgsInfo(FILE * const F, unsigned int const &Version);
void WriteHistoryTag(std::string const &tag, std::string value);
// Terminal progress
void SetupTerminalScrollArea(int nr_scrolled_rows);
void SendTerminalProgress(float percentage);
// apport integration

Loading…
Cancel
Save