X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/8336ae355b8a22877cd233063c715688155aa617..9ce3cfc9309c55cc01018c88c1ca82779fd74431:/apt-pkg/install-progress.cc diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 1d15228c2..a3a4cc0e1 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -1,8 +1,7 @@ #include #include #include - -#include +#include #include @@ -10,10 +9,38 @@ #include #include #include +#include +#include namespace APT { namespace Progress { + +/* Return a APT::Progress::PackageManager based on the global + * apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd) + */ +PackageManager* PackageManagerProgressFactory() +{ + // select the right progress + int status_fd = _config->FindI("APT::Status-Fd", -1); + int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1); + + APT::Progress::PackageManager *progress = NULL; + if (status_deb822_fd > 0) + progress = new APT::Progress::PackageManagerProgressDeb822Fd( + status_deb822_fd); + else if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); + return progress; +} + bool PackageManager::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, @@ -42,7 +69,7 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressFd::Start() +void PackageManagerProgressFd::StartDpkg() { if(OutStatusFd <= 0) return; @@ -62,8 +89,6 @@ void PackageManagerProgressFd::Start() void PackageManagerProgressFd::Stop() { - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); } void PackageManagerProgressFd::Error(std::string PackageName, @@ -130,7 +155,7 @@ void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressDeb822Fd::Start() +void PackageManagerProgressDeb822Fd::StartDpkg() { // FIXME: use SetCloseExec here once it taught about throwing // exceptions instead of doing _exit(100) on failure @@ -147,8 +172,6 @@ void PackageManagerProgressDeb822Fd::Start() void PackageManagerProgressDeb822Fd::Stop() { - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); } void PackageManagerProgressDeb822Fd::Error(std::string PackageName, @@ -201,8 +224,46 @@ bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, } +PackageManagerFancy::PackageManagerFancy() + : child_pty(-1) +{ + // setup terminal size + old_SIGWINCH = signal(SIGWINCH, PackageManagerFancy::staticSIGWINCH); + instances.push_back(this); +} +std::vector PackageManagerFancy::instances; + +PackageManagerFancy::~PackageManagerFancy() +{ + instances.erase(find(instances.begin(), instances.end(), this)); + signal(SIGWINCH, old_SIGWINCH); +} + +void PackageManagerFancy::staticSIGWINCH(int signum) +{ + std::vector::const_iterator I; + for(I = instances.begin(); I != instances.end(); ++I) + (*I)->HandleSIGWINCH(signum); +} + +int PackageManagerFancy::GetNumberTerminalRows() +{ + struct winsize win; + // FIXME: get from "child_pty" instead? + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) != 0) + return -1; + + if(_config->FindB("Debug::InstallProgress::Fancy", false) == true) + std::cerr << "GetNumberTerminalRows: " << win.ws_row << std::endl; + + return win.ws_row; +} + void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { + if(_config->FindB("Debug::InstallProgress::Fancy", false) == true) + std::cerr << "SetupTerminalScrollArea: " << nr_rows << std::endl; + // scroll down a bit to avoid visual glitch when the screen // area shrinks by one row std::cout << "\n"; @@ -211,34 +272,41 @@ void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) std::cout << "\033[s"; // set scroll region (this will place the cursor in the top left) - std::cout << "\033[1;" << nr_rows - 1 << "r"; + std::cout << "\033[0;" << 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; + // ensure its flushed std::flush(std::cout); + + // setup tty size to ensure xterm/linux console are working properly too + // see bug #731738 + struct winsize win; + ioctl(child_pty, TIOCGWINSZ, (char *)&win); + win.ws_row = nr_rows - 1; + ioctl(child_pty, TIOCSWINSZ, (char *)&win); } -PackageManagerFancy::PackageManagerFancy() - : nr_terminal_rows(-1) +void PackageManagerFancy::HandleSIGWINCH(int) { - struct winsize win; - if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) - { - nr_terminal_rows = win.ws_row; - } + int nr_terminal_rows = GetNumberTerminalRows(); + SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Start() +void PackageManagerFancy::Start(int a_child_pty) { + child_pty = a_child_pty; + int nr_terminal_rows = GetNumberTerminalRows(); if (nr_terminal_rows > 0) SetupTerminalScrollArea(nr_terminal_rows); } void PackageManagerFancy::Stop() { + int nr_terminal_rows = GetNumberTerminalRows(); if (nr_terminal_rows > 0) { SetupTerminalScrollArea(nr_terminal_rows + 1); @@ -247,6 +315,7 @@ void PackageManagerFancy::Stop() static const char* clear_screen_below_cursor = "\033[J"; std::cout << clear_screen_below_cursor; } + child_pty = -1; } bool PackageManagerFancy::StatusChanged(std::string PackageName, @@ -258,7 +327,7 @@ bool PackageManagerFancy::StatusChanged(std::string PackageName, HumanReadableAction)) return false; - int row = nr_terminal_rows; + int row = GetNumberTerminalRows(); static string save_cursor = "\033[s"; static string restore_cursor = "\033[u";